Skip to content

Instantly share code, notes, and snippets.

@datalogics-robl
Created August 12, 2013 20:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save datalogics-robl/6215182 to your computer and use it in GitHub Desktop.
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
#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
@datalogics-kam
Copy link

BTW, you can, and I recommend it, make these private. Anybody with the link can still read them.

@datalogics-robl
Copy link
Author

Is it possible to change this one?

@scottcc
Copy link

scottcc commented Jan 28, 2014

Say guys, did you ever figure out a workable objective C implementation of UUID5 (or UUID3)? I see this was attempted some time ago (not sure if it was intended to be public from the comments there). Just curious before I attempt implementing RFC 4122 if you guys found a way beyond this.

@scottcc
Copy link

scottcc commented Jan 29, 2014

Never mind, implementation wasn't hard, got it working.

@superduper
Copy link

Just in case anyone needs uuid5 calculation in url namespace https://gist.github.com/superduper/177aab4b9700e41103e3

@eliburke
Copy link

eliburke commented May 1, 2015

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment