I need to generate a hash using HMAC SHA256. I am using the following code in Java. I need an equivalent code in Objective-C.
javax.crypto.Mac mac = javax.crypto.Mac.getInstance(type);
javax.crypto.spec.SecretKeySpec secret = new javax.crypto.spec.SecretKeySpec(key.getBytes(), type);
mac.init(secret);
byte[] digest = mac.doFinal(value.getBytes());
StringBuilder sb = new StringBuilder(digest.length * 2);
String s="";
for (byte b: digest) {
s = Integer.toHexString(b);
if (s.length() == 1) {
sb.append('0');
}
sb.append(s);
}
return sb.toString();
Key = YARJSuwP5Oo6/r47LczzWjUx/T8ioAJpUK2YfdI/ZshlTUP8q4ujEVjC0seEUAAtS6YEE1Veghz+IDbNQb+2KQ==
Value =
id=456|time=19:10|nonce=8
Output =
4effffffd8ffffffce7cffffffc4ffffffc71b2f72ffffffdc21ffffffa1ffffffe0ffffffe62d32550b0771296bffffff9c1159ffffffdeffffff8675ffffff9928654c
I have this Objective-C function:
//Hash method Definition
- (NSString *)getHashEncription:(NSString *)key andData:(NSString *)data{
NSLog(@"Secret Key %@ And Data %@", key, data);
const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];
unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
//HmacSHA256
CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC
length:sizeof(cHMAC)];
[Base64 initialize];
NSString *b64EncStr = [Base64 encode:HMAC];
NSLog(@"Base 64 encoded = %@",b64EncStr);
NSLog(@"NSData Value %@", HMAC);
// unsigned char hashedChars[32];
// NSString *inputString;
// inputString = [NSString stringWithFormat:@"hello"];
// NSData * inputData = [inputString dataUsingEncoding:NSUTF8StringEncoding];
// CC_SHA256(inputData.bytes, inputData.length, hashedChars);
return [[NSString alloc] initWithData:HMAC encoding:NSASCIIStringEncoding];
}//End of getHashEncription
The output that I am getting is this:
8736bc4aa7fc3aa071f2b4262b6972a89d2861559a20afa765e46ff17cb181a9
I tried removing the base64 encoding, but it didn't work.
Any suggestions are most welcome.
First, enter the plain-text and the cryptographic key to generate the code. Then, you can use select the hash function you want to apply for hashing. The default is SHA-256. Then you can submit your request by clicking on the compute hash button to generate the HMAC authentication code for you.
A: HMAC (Hashed Message Authentication Code) uses SHA-1 internally. The difference is that a MAC uses a secret key.
The minimum length for an SHA-256 HMAC key is 32 bytes. A key longer than 32 bytes does not significantly increase the function strength unless the randomness of the key is considered weak. A key longer than 64 bytes will be hashed before it is used.
The secret key for HMACSHA256 encryption. The key can be any length. However, the recommended size is 64 bytes. If the key is more than 64 bytes long, it is hashed (using SHA-256) to derive a 64-byte key.
You need to fix your Java hmac printer, because 4effffffd8ffffffce7cffffffc4ffffffc71b2f72ffffffdc21ffffffa1ffffffe0ffffffe62d32550b0771296bffffff9c1159ffffffdeffffff8675ffffff9928654c
isn't valid. All those ffffff
in there are a giveaway that you are sign-extending the bytes to 32-bit signed integers before converting them to hex. Presumably the correct hmac is 4ed8ce7cc4c71b2f72dc21a1e0e62d32550b0771296b9c1159de86759928654c
.
Anyway, I suspect you are calling your method incorrectly. I copied your code into a test program which gives me this output for your key and data:
2011-12-10 13:03:38.231 hmactest[8251:707] test hmac = <4ed8ce7c c4c71b2f 72dc21a1 e0e62d32 550b0771 296b9c11 59de8675 9928654c>
That matches your desired output (except for the sign-extension errors).
Here's my test program:
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonHMAC.h>
NSData *hmacForKeyAndData(NSString *key, NSString *data)
{
const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];
unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
return [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
}
int main (int argc, const char * argv[])
{
@autoreleasepool {
// Compare to http://en.wikipedia.org/wiki/HMAC#Examples_of_HMAC_.28MD5.2C_SHA1.2C_SHA256_.29
NSLog(@"empty hmac = %@", hmacForKeyAndData(@"", @""));
NSLog(@"test hmac = %@", hmacForKeyAndData(@"YARJSuwP5Oo6/r47LczzWjUx/T8ioAJpUK2YfdI/ZshlTUP8q4ujEVjC0seEUAAtS6YEE1Veghz+IDbNQb+2KQ==", @"id=456|time=19:10|nonce=8"));
}
return 0;
}
Line
CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
has a bug
If in your key would be 0x00 byte strlen(cKey)
would give wrong length and hmac generation process will produce some rubbish.
In my implementation I have changed that to:
CCHmac(kCCHmacAlgSHA256, cKey, [key length], cData, [data length], cHMAC);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With