Question

I am having trouble hashing my device's id into a 64 bit (or greater) representation and then converting that into a base-31 representation. Any one have any tips or guidance? I have been looking online and can't seem to find much.

Each base-31 digit should then be represented by the this list: 2 3 4 5 6 7 8 9 A B C D E F G H J K M N P Q R S T U V W X Y Z

What I've tried:

NSString *myID = [[[UIDevice currentDevice] identifierForVendor]UUIDString];
NSLog(@"Non Hash: %@", myID); //Logs the 36 character string
myID = [NSString stringWithFormat:@"%lu",(unsigned long)[myID hash]]; // Changed thanks to rokjarc
NSLog(@"Hash: %@", myID); //Logs same 36 character string


//Logs 36 character string
NSLog(@"UUIDString: %@", [[[UIDevice currentDevice] identifierForVendor] UUIDString]);

//Logs out a 10 character numeric value
NSLog(@"Hash: %lu", (unsigned long)[[[[UIDevice currentDevice] identifierForVendor] UUIDString] hash]);

//Logs out a 2 character numeric value
NSLog(@"LongLong: %lld", [[[[UIDevice currentDevice] identifierForVendor] UUIDString] longLongValue]);
Was it helpful?

Solution

[[[UIDevice currentDevice] identifierForVendor]UUIDString] returns a UUID which is comprised of 32 hex characters which is 128 bits. 12 base31 characters can only represent 63 bits. Thus the entire UUID can not be represented.

Best bet is to run the UUID through SHA (which seems to be what [myID hash] does) and convert 63 of the bits of that into 12 base31 characters.

The reason for the hash function (SHA) is to remove any pattern in the UUID, each bit in the result of SHA is equally likely to be a 1 or 0.

Notes: 31^12 = 7.87E17 and 2^64 = 1.84E19
thus a 64 bit number can not be represented in 12 base 31 characters. 63 bit can however.

Base32 is a lot simpler than base31 for values larger than 64 bits.

Here is a code sample that creates a string of base31 characters from a 64-bit integer:

uint64_t uid = 14467240737094581;

NSString *baseCharacters = @"23456789ABCDEFGHJKMNPQRSTUVWXYZ";
NSUInteger base = baseCharacters.length;
NSMutableString *baseString = [NSMutableString new];
while (baseString.length < 12) {
    uint64_t remainder = uid % base;
    uid /= base;
    NSString *baseCharacter = [baseCharacters substringWithRange:NSMakeRange(remainder, 1)];
    [baseString insertString:baseCharacter atIndex:0];
}
NSLog(@"baseString: %@", baseString);

NSLog output:
baseString: 2KP7MAR5CX86

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top