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;
}