1

Ruby code:

  a = OpenSSL::HMAC.digest('sha1', 'secret', 'example')

and then:

 Base64.encode64(a).chomp

yields

 aMp6Zw1+hHVMmwWXoFp/Aaipc20=

iPhone:

+ (NSData *)hmac:(NSString *)input withKey:(NSString *)key {
    const char *cstrInput = [input cStringUsingEncoding:NSASCIIStringEncoding];
    const char *cstrKey = [key cStringUsingEncoding:NSASCIIStringEncoding];
    NSData *data = [NSData dataWithBytes:cstrInput length:input.length];

    unsigned char chmac[CC_SHA1_DIGEST_LENGTH];
    CCHmac(kCCHmacAlgSHA1, cstrKey, strlen(cstrKey), data, [data length], &chmac);

    NSData *hmacData = [[NSData alloc] initWithBytes:chmac length:sizeof(chmac)];
    return [hmacData autorelease];
}

And

[XICrypto hmac:@"example" withKey:@"secret"];
NSLog(@"HMACData: %@",[HMACData description]);
NSString *HMACEncodedString = [HMACData base64Encoding];

(Where base64Encoding method is from Alex Reynold's answer on Cocoa Base 64 Implementation for REST Auth)

Results yield

Qm+ManmzmtfhpOzFdf8UHW43L5o=

So these methods are not performing the same operations, why?

EDIT: digest and key were backwards in the Rails call. Fixed that, yet the result is still different from the iPhone's call.

Community
  • 1
  • 1
quantumpotato
  • 9,637
  • 14
  • 70
  • 146
  • Have you looked here? I'm not sure you're using the correct function to perform your SHA-1 encryption - http://stackoverflow.com/questions/3468268/objective-c-sha1. – Perception Jul 18 '11 at 15:52
  • 1
    CCHmac is supposed to be the 1 function call for init update and final. I am looking into the issue and string encoding is making the biggest difference. – Joe Jul 18 '11 at 15:54
  • @Perception, I don't see the option for a secret key in that post. @Joe, Do you see any issue with the encoding? – quantumpotato Jul 18 '11 at 16:15
  • Had the rails call key & data backwards as per the docs: HMAC.digest(digest, key, data) → aString Updated post with correct param order & new result aMp6Zw1+hHVMmwWXoFp/Aaipc20= – quantumpotato Jul 18 '11 at 16:20
  • @quanumpotato - your right, you need to be able to pass in the key so the other post doesn't help much, if any. @Joe might be onto something with the character encoding. – Perception Jul 18 '11 at 16:28

1 Answers1

3

Yes I see your comment after I figured out that part on my own :), your rails call is backwards, your next issue is encoding. When ever you want the correct length of bytes when using string encoding use lengthOfBytesUsingEncoding:.

+ (NSData *)hmac:(NSString *)input withKey:(NSString *)key {
    NSStringEncoding encoding = NSASCIIStringEncoding;
    const char *cstrInput = [input cStringUsingEncoding:encoding];
    NSUInteger inputLength = [input lengthOfBytesUsingEncoding:encoding];
    const char *cstrKey = [key cStringUsingEncoding:encoding];
    NSUInteger keyLength = [key lengthOfBytesUsingEncoding:encoding];

    unsigned char chmac[CC_SHA1_DIGEST_LENGTH];
    CCHmac(kCCHmacAlgSHA1, cstrKey, keyLength, cstrInput, inputLength, &chmac);

    return [[[NSData alloc] initWithBytes:chmac length:sizeof(chmac)] autorelease];
}

I logged the contents of the data and get 68ca7a67 0d7e8475 4c9b0597 a05a7f01 a8a9736d and if you paste that into the hex field of this translator you will get aMp6Zw1+hHVMmwWXoFp/Aaipc20= in the base64 field.

Joe
  • 56,979
  • 9
  • 128
  • 135
  • Your orignal method could be fixed also by using strlen(cstrInput) when creating the data instead of input.length to make it a quick fix. – Joe Jul 18 '11 at 16:57