xcode ios HMAC SHA 256 hashing

19
我正在尝试在iOS上进行hmacshad256哈希,因为这是我为WCF服务API所做的哈希。 我一直在尝试寻找相关信息,但通常只能得到SHA-256哈希。

这是我唯一的参考资料:

需要在Objective C中生成HMAC SHA256哈希,就像Java中一样

我不确定这是否是唯一的方法(导入Java hmac类)

任何帮助都将不胜感激。

谢谢!


嗯.. 有人之前删除了对此的回复? - gdubs
这不是你正在寻找的内容吗? https://dev59.com/h2025IYBdhLWcg3wr4B6 - DenNukem
3个回答

36
NSString * parameters = @"string to hash"
NSString *salt = @"saltStringHere";
NSData *saltData = [salt dataUsingEncoding:NSUTF8StringEncoding];
NSData *paramData = [parameters dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData* hash = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH ];
CCHmac(kCCHmacAlgSHA256, saltData.bytes, saltData.length, paramData.bytes, paramData.length, hash.mutableBytes);
NSString *base64Hash = [hash base64Encoding];

而且

#import <CommonCrypto/CommonHMAC.h>

自从iOS 7.0起,base64Encoding已被弃用,因此最后一行应该是:

NSString *base64Hash = [hash base64EncodedStringWithOptions:0];

2
现在的选择器是 -base64EncodedStringWithOptions:。 - ff10
1
请编辑您的答案,并写上我们需要添加 #import "NSData+Base64.h"。 - SteBra
1
@Stebra 嗯,你不需要导入NSData+Base64.h。你可以把这段代码放在任何你想要的地方。但是确实,使用扩展NSData的类别可能是最好的方法。 - Juraj Antas
1
由于盐通常是公开的,这可能会产生误导。实际上,你应该在那里使用秘密密钥! - Raphael

8

这是我从其他答案中整合而来的解决方案:

通过更改CC_SHA256_DIGEST_LENGTH和kCCHmacAlgSHA256,可以轻松地将其适应于其他哈希类型。

如果您有兴趣这样做,请查看CommonCrypto库中的CommonDigest.h文件。

#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonCrypto.h>

+ (NSString *)hmac:(NSString *)plaintext withKey:(NSString *)key
{
    const char *cKey  = [key cStringUsingEncoding:NSASCIIStringEncoding];
    const char *cData = [plaintext cStringUsingEncoding:NSASCIIStringEncoding];
    unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
    CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
    NSData *HMACData = [NSData dataWithBytes:cHMAC length:sizeof(cHMAC)];
    const unsigned char *buffer = (const unsigned char *)[HMACData bytes];
    NSMutableString *HMAC = [NSMutableString stringWithCapacity:HMACData.length * 2];
    for (int i = 0; i < HMACData.length; ++i){
        [HMAC appendFormat:@"%02x", buffer[i]];
    }

    return HMAC;
}

本代码已在iOS 8.x和iOS 7.x上进行了测试。


2
这假设明文和密钥是ASCII编码,这在当今多语言甚至表情符号的环境中非常受限制。请注意@Juraj Antas不需要字符数组。此实现唯一提供的是十六进制输出而不是Base64,值得在答案顶部提及。 - zaph
谢谢Zaph。是的,在我的情况下,我知道它们是。 - Alex Zavatone
4
不需要使用“在我的情况下”这样的措辞,原文内容为:This is an answer so "in my case" does not apply. Instead of using NSASCIIStringEncoding just use NSUTF8StringEncoding。翻译为:这是一条回答,所以“在我的情况下”不适用。不要使用NSASCIIStringEncoding,而是使用NSUTF8StringEncoding - zaph
目前这个方法即使将NSASCIIStringEncoding替换为NSUTF8StringEncoding,在使用高ASCII字符(如¥€£•‹›)时仍会返回错误的哈希值。我正在努力修复它。 - Alex Zavatone

1

+ (NSString *)hmacSHA256EncryptString{


    NSString * parameterSecret = @"input secret key";
    NSString *plainString = @"input encrypt content string";
    const char *secretKey  = [parameterSecret cStringUsingEncoding:NSUTF8StringEncoding];
    const char *plainData = [plainString cStringUsingEncoding:NSUTF8StringEncoding];
    unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
    CCHmac(kCCHmacAlgSHA256, secretKey, strlen(secretKey), plainData, strlen(plainData), cHMAC);
    NSData *HMACData = [NSData dataWithBytes:cHMAC length:sizeof(cHMAC)];
    const unsigned char *bufferChar = (const unsigned char *)[HMACData bytes];
    NSMutableString *hmacString = [NSMutableString stringWithCapacity:HMACData.length * 2];
    for (int i = 0; i < HMACData.length; ++i){
        [hmacString appendFormat:@"%02x", bufferChar[i]];
    }
    return hmacString;
    
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接