Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need to generate HMAC SHA256 hash in Objective C as in Java

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.

like image 316
Tushar Avatar asked Dec 10 '11 18:12

Tushar


People also ask

How do I get the HMAC sha256 key?

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.

What is the difference between HMAC and SHA?

A: HMAC (Hashed Message Authentication Code) uses SHA-1 internally. The difference is that a MAC uses a secret key.

How long is HMAC sha256?

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.

What is secret key in HMACSHA256?

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.


2 Answers

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;
}
like image 67
rob mayoff Avatar answered Oct 17 '22 13:10

rob mayoff


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);
like image 29
Azeraht Avatar answered Oct 17 '22 13:10

Azeraht