static CFDataRef digestString(CFStringRef str) { CFDataRef retval = NULL; CFErrorRef error = NULL; CFDataRef inputString = CFStringCreateExternalRepresentation(kCFAllocatorDefault, str, kCFStringEncodingUTF8, 0xff); SecTransformRef digestTrans = SecDigestTransformCreate(kSecDigestSHA2, 256, &error); if(error == NULL) { SecTransformSetAttribute(digestTrans, kSecTransformInputAttributeName, inputString, &error); if(error == NULL) { retval = SecTransformExecute(digestTrans, &error); if(retval == NULL) { secDebug(ASL_LEVEL_ERR, "Couldn't create digest %s\n", CFStringGetCStringPtr(CFErrorCopyFailureReason(error), kCFStringEncodingUTF8)); } } CFRelease(digestTrans); } CFRelease(inputString); return retval; }
CFDataRef APCreateHashFromDictionary(CFDictionaryRef dict) { __block CFErrorRef error = NULL; __block SecTransformRef hashFunction = NULL; void(^cleanup)(void) = ^(void) { if (error != NULL) { CFShow(error); CFRelease(error); error = NULL; } if (hashFunction != NULL) { CFRelease(hashFunction); hashFunction = NULL; } }; // Get the number of elements CFIndex count = CFDictionaryGetCount(dict); // Load the keys and build up the key array CFMutableArrayRef keyArray = CFArrayCreateMutable(kCFAllocatorDefault, count, NULL); CFStringRef keys[count]; CFDictionaryGetKeysAndValues(dict, (const void**)&keys, NULL); for (int idx = 0; idx < count; idx++) { // Skip the signature key if (CFStringCompare(keys[idx], CFSTR("Signature"), 0) == kCFCompareEqualTo) { continue; } CFArrayAppendValue(keyArray, keys[idx]); } // Sort the array int context = kCFCompareCaseInsensitive; CFArraySortValues(keyArray, CFRangeMake(0, count-1), (CFComparatorFunction)CFStringCompare, &context); // Build the data CFMutableDataRef dictData = CFDataCreateMutable(kCFAllocatorDefault, 0); int keyCount = CFArrayGetCount(keyArray); for (int keyIndex = 0; keyIndex < keyCount; keyIndex++) { CFStringRef key = CFArrayGetValueAtIndex(keyArray, keyIndex); CFStringRef value = CFDictionaryGetValue(dict, key); CFDataRef valueData = CFStringCreateExternalRepresentation(kCFAllocatorDefault, value, kCFStringEncodingUTF8, 0); const UInt8 *valueBuffer = CFDataGetBytePtr(valueData); CFDataAppendBytes(dictData, valueBuffer, CFDataGetLength(valueData)); CFRelease(valueData); } // Hash the data hashFunction = SecDigestTransformCreate(kSecDigestSHA1, 0, &error); if (error != NULL) { CFRelease(dictData); cleanup(); return NULL; } SecTransformSetAttribute(hashFunction, kSecTransformInputAttributeName, dictData, &error); CFDataRef hashData = SecTransformExecute(hashFunction, &error); CFRelease(dictData); if (error != NULL) { cleanup(); if (hashData) { CFRelease(hashData); } return NULL; } cleanup(); return hashData; }