【问题标题】:Need to generate HMAC SHA256 hash in Objective C as in Java需要像在 Java 中一样在 Objective C 中生成 HMAC SHA256 哈希
【发布时间】:2012-01-17 12:54:45
【问题描述】:

我需要使用 HMAC SHA256 生成哈希。我在 Java 中使用以下代码。我需要 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();

密钥 = YARJSuwP5Oo6/r47LczzWjUx/T8ioAJpUK2YfdI/ZshlTUP8q4ujEVjC0seEUAAtS6YEE1Veghz+IDbNQb+2KQ==

价值 =

id=456|time=19:10|nonce=8

输出 =

4effffffd8ffffffce7cffffffc4ffffffc71b2f72ffffffdc21ffffffa1ffffffe0ffffffe62d32550b0771296bffffff9c1159ffffffdeffffff8675ffffff9928654c

我有这个 Objective-C 函数:

  //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

我得到的输出是这样的:

8736bc4aa7fc3aa071f2b4262b6972a89d2861559a20afa765e46ff17cb181a9

我尝试删除 base64 编码,但没有成功。

欢迎提出任何建议。

【问题讨论】:

  • 你有 Base64 作为类别类吗?
  • CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
  • 嗨 Tushar,我必须使用 java 代码为 facebook 生成应用程序秘密证明。你在这里有类型参数它的值是什么。我尝试使用 SHA-256,但没有发现任何提供者发现异常

标签: java objective-c hash hmac


【解决方案1】:

您需要修复您的 Java hmac 打印机,因为 4effffffd8ffffffce7cffffffc4ffffffc71b2f72ffffffdc21ffffffa1ffffffe0ffffffe62d32550b0771296bffffff9c1159ffffffdeffffff8675ffffff9928654c 无效。所有那些ffffff 都有一个赠品,即您将字节符号扩展为 32 位有符号整数,然后再将它们转换为十六进制。大概正确的hmac是4ed8ce7cc4c71b2f72dc21a1e0e62d32550b0771296b9c1159de86759928654c

无论如何,我怀疑您错误地调用了您的方法。我将您的代码复制到了一个测试程序中,该程序为您的密钥和数据提供了以下输出:

2011-12-10 13:03:38.231 hmactest[8251:707] test hmac = <4ed8ce7c c4c71b2f 72dc21a1 e0e62d32 550b0771 296b9c11 59de8675 9928654c>

这与您想要的输出相匹配(符号扩展错误除外)。

这是我的测试程序:

#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;
}

【讨论】:

  • 嗨,我遇到了同样的问题,您的解决方案帮助我解决了我从 ios 生成的 hmac 的不准确性。我唯一的问题是当它返回 NSData 时,它的返回看起来像这样 它基本上会有空格。同时,在我的 API 上,它将是一个完整的字符串(“2efb00aba01a3f5b674fba3063b43fee7a93569471....”)。我将 c# btw 用于 api。我的问题是我是否只是删除空格,以便我可以将正确的签名传递给我的 api?还是我使用 base64 将其转换为字符串(这会改变值)?
  • CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
  • 你不需要释放(cHMAC)吗?为了避免由此产生的无限内存增长?为什么它不是一个指针..?
  • 你不需要释放它,因为它是在堆栈上分配的。
  • 我遇到的问题是我的特定数据(我使用与你们相同的 hMac 例程),当我执行const char *cData = [data cStringUsingEncoding: NSASCIIStringEncoding]; 时,返回 cData = NULL。现在我只需要弄清楚为什么。 (我有一个非常狭窄的“这个数据有效,现在这个稍微修改过的数据没有”测试用例,我只需要区分它们并弄清楚。)
【解决方案2】:

线

CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);

有错误

如果你的密钥是 0x00 字节 strlen(cKey) 会给出错误的长度并且 hmac 生成过程会产生一些垃圾。

在我的实现中,我将其更改为:

CCHmac(kCCHmacAlgSHA256, cKey, [key length], cData, [data length], cHMAC);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-10
    • 2016-08-20
    • 1970-01-01
    • 1970-01-01
    • 2016-08-03
    • 2016-07-09
    • 1970-01-01
    • 2020-11-27
    相关资源
    最近更新 更多