Re: Need localization-proof method of transporting dates.
Re: Need localization-proof method of transporting dates.
- Subject: Re: Need localization-proof method of transporting dates.
- From: Graham Cox <email@hidden>
- Date: Mon, 6 Apr 2009 09:23:01 +1000
On 06/04/2009, at 1:15 AM, Michael Ash wrote:
Note that, as far as I know, there is no guarantee that -hash will
return the same value for the same object across runs of your program.
Apple is free to change their algorithm in an OS update, and could
conceivably (although I don't see why) switch between different
algorithms at process start time. You'll want to use your own hashing
algorithm for this.
Yes, I realise you're right. I've been assuming that -hash is derived
in a simple way that is stable over time, OS version, etc.
The previous hashing approach used an object's -description method
which was taken from Aquatic Prime's code for hashing a dictionary,
but that was failing on dates with locale changes. There's no
guarantee that -description will never change either.
This leaves me with a problem - how to generate a SHA-1 hash of an
arbitrary dictionary that is likely to remain stable under different
architectures, OS versions, and so on. Note that I currently also use
the dictionary keys as part of the hashing function, so that part is
probably safe. But the hash definitely has to be sensitive to the
values for each key also.
Here's the current code:
@implementation NSData (SHA1Hash)
- (NSData*) sha1Hash
{
// calculates the 160 bit SHA-1 digest of the given data
unsigned char* digest = (unsigned char*) malloc(20);
SHA1([self bytes], [self length], digest);
return [[self class] dataWithBytesNoCopy:digest length:20];
}
+ (NSData*) sha1HashWithDictionary:(NSDictionary*) dict
{
// hashes the contents of the dictionary and returns the SHA-1 digest
resulting. This takes account of the keys and values in the dictionary
// to provide a reliable signature for the dictionary. The dictionary
passed must not already contain the digest we are trying to compute!
// WARNING: using -description here (as AQP) makes the hash sensitive
to system settings such as date format if the dictionary contains
dates, etc. Thus
// we must not use this is a way to verify the dictionary content.
Instead we use the -hash value returned by the object.
NSMutableArray* keys = [[dict allKeys] mutableCopy];
[keys sortUsingSelector:@selector(caseInsensitiveCompare:)];
NSEnumerator* iter = [keys objectEnumerator];
NSString* key;
NSMutableData* dictData = [NSMutableData data];
while(( key = [iter nextObject]))
{
id currentValue = [dict objectForKey:key];
//NSLog(@"key = %@, obj = %@, hash = %d", key, currentValue,
[currentValue hash]);
unsigned hash = [currentValue hash];
[dictData appendBytes:&hash length:sizeof(unsigned)];
char* description = (char*)[key UTF8String];
[dictData appendBytes:description length:strlen(description)];
}
[keys release];
return [dictData sha1Hash];
}
@end
So if anyone has any bright ideas about how I could successfully
implement this, I'm all ears!
cheers, Graham
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden