views:

1065

answers:

1

I have a Cocoa app send some data along with a SHA1 hash of that data to a Rails app which verifies that the data and the hash match, but they do not.

To be sure I have logged hex versions of the data that is hashed to the console at both the Rails and Cocoa sides, and they match exactly.

Here's the Cocoa part:

#import <CommonCrypto/CommonDigest.h>

//...

- (NSData *)dataOfSHA1Hash
{
    unsigned char hashBytes[CC_SHA1_DIGEST_LENGTH];
    CC_SHA1([self bytes], CC_SHA1_DIGEST_LENGTH, hashBytes);

    return [NSData dataWithBytes:hashBytes length:CC_SHA1_DIGEST_LENGTH];
}

//...

NSData *signatureData = [signedData dataOfSHA1Hash];
NSString *signature = [signatureData hexadecimalString];

..and Rails:

Digest::SHA1.hexdigest(signed_data)

Note that -hexadecimalString is a custom extension to NSData (didn't seem to be built in), which I've tested. That method does not seem to be the problem.

So, why don't my SHA1 hashes match on the same data? Any ideas?

Edit: example

For the string "Hello World!"

Cocoa: f98ee9c814c2f3c66ccdca641298d12cd26741ec
Rails: 2ef7bde608ce5404e97d5f042f95f89f1c232871

Cocoa:

NSMutableData *signedData = [[NSMutableData alloc] init];
[signedData appendData:[@"Hello World!" dataUsingEncoding:NSUTF8StringEncoding]];

NSData *signatureData = [signedData dataOfSHA1Hash];
[signedData release];
NSString *signature = [signatureData hexadecimalString];

NSLog(@"Signature: %@", signature);
// output: Signature: f98ee9c814c2f3c66ccdca641298d12cd26741ec

Ruby:

>> Digest::SHA1.hexdigest("Hello World!")
=> "2ef7bde608ce5404e97d5f042f95f89f1c232871"
+5  A: 

Found the error, stupid little thing:

-CC_SHA1([self bytes], CC_SHA1_DIGEST_LENGTH, hashBytes);
+CC_SHA1([self bytes], [self length], hashBytes);

I sent the length of the digest instead of the length of the data. Don't know how I could've made such a mistake – and then overlook it for hours.

sjmulder