Created
August 12, 2013 20:59
-
-
Save datalogics-robl/6215182 to your computer and use it in GitHub Desktop.
Example code for calculating a UUID 5 on iOS. It does not give correct results. EXPECTED: b31c0937-b03b-5a5e-b47a-b80881530929
ACTUAL: 59F5ADDE-9E13-578E-BB37-C3200E80A1B9
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "NSUUID+DLExtensions.h" | |
#import <CommonCrypto/CommonDigest.h> | |
@implementation NSUUID (DLExtensions) | |
+ (NSUUID*)withNamespaceUUID:(NSUUID*)namespace name:(NSString*)name | |
{ | |
NSString *concatenatedName = [[namespace UUIDString] stringByAppendingString:name]; | |
NSData *data = [concatenatedName dataUsingEncoding:NSUTF8StringEncoding]; | |
uint8_t digest[CC_SHA1_DIGEST_LENGTH]; | |
uuid_t bytes; | |
CC_SHA1(data.bytes, data.length, digest); | |
// TEMPORARY--Just log the new UUID | |
NSMutableString *dontUse = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH]; | |
for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) { | |
[dontUse appendFormat:@"%02x", digest[i]]; | |
} | |
NSLog(@"CRYPTO'D STRING = %@", dontUse); | |
// END TEMPORARY | |
// Fill in the UUID bytes, masking in the version and reserved bits | |
bytes[0] = digest[0]; // time_low | |
bytes[1] = digest[1]; | |
bytes[2] = digest[2]; | |
bytes[3] = digest[3]; | |
bytes[4] = digest[4]; // time_mid | |
bytes[5] = digest[5]; | |
bytes[6] = ((digest[6] & 0x0F) | 0x50); // time_hi_and_version | |
bytes[7] = digest[7]; | |
bytes[8] = ((digest[8] & 0x3F) | 0xB0); // clock_seq_hi_and_reserved | |
bytes[9] = digest[9]; // clock_seq_low | |
bytes[10] = digest[10]; // node | |
bytes[11] = digest[11]; | |
bytes[12] = digest[12]; | |
bytes[13] = digest[13]; | |
bytes[14] = digest[14]; | |
bytes[15] = digest[15]; | |
// TEMPORARY | |
NSLog(@"Computed UUID: %@", [[[[NSUUID alloc] initWithUUIDBytes:bytes] autorelease] UUIDString]); | |
// END TEMPORARY | |
return [[[NSUUID alloc] initWithUUIDBytes:bytes] autorelease]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I had problems with both Rob and Victor's implementations because I needed to interoperate with (and match) uuid5 strings generated by a python backend. Using their code as a starting point I've created a drop-in NSUUID category that works correctly. It's MIT licensed so you are free to do with it as you like.
https://gist.github.com/eliburke/1a55ed616bb15a7f908b
If you prefer to fix Rob's code, you need to use the raw bytes from the namespace UUID and change his clock_seq_hi_and_reserved line to use 0x80 instead of 0xB0.
If you prefer to fix Victor's code, change his calculation of bytes[8] from
bytes[8] = ((bytes[8] | 0x40) & 0x7F); // bad code, sets bits to 0100 xxxx
bytes[8] = ((bytes[8] & 0x3F) | 0x80); // good code, sets bits to 10xx xxxx