带有kCCHmacAlgSHA1的CCHmac具有不一致的输出长度

时间:2013-12-06 21:13:39

标签: objective-c c oauth hmac

我正在开发iOS的oauth库,大约有10%到15%的请求失败,因为我的库生成的oauth_signature不正确。我已将此问题追溯到CCHmac(),返回意外结果。当hmac哈希的长度不正确时,签名失败。为了验证这个问题,我运行了这段代码:

NSString *key = @"25f108b539761bd43b6c66b64fb191c8";

for (int i = 0; i < 25; i++) {
    unsigned int chunks[4] = {
        arc4random() % ((int) pow(256, 4)),
        arc4random() % ((int) pow(256, 4)),
        arc4random() % ((int) pow(256, 4)),
        arc4random() % ((int) pow(256, 4))
    };

    // Generate a random input string of 32 hex chars
    NSString *input = [NSString stringWithFormat:@"%08x%08x%08x%08x", chunks[0], chunks[1], chunks[2], chunks[3]];

    unsigned char output[CC_SHA1_DIGEST_LENGTH];

    CCHmac(kCCHmacAlgSHA1, key.UTF8String, key.length, input.UTF8String, input.length, output);

    NSLog(@"HMAC Hash Length: %02lu", strlen(output));
}

...得到了这个输出:

2013-12-06 16:05:24.596 ODB[98281:70b] HMAC Hash Length: 40
2013-12-06 16:05:24.596 ODB[98281:70b] HMAC Hash Length: 20
2013-12-06 16:05:24.596 ODB[98281:70b] HMAC Hash Length: 41
2013-12-06 16:05:24.596 ODB[98281:70b] HMAC Hash Length: 35
2013-12-06 16:05:24.596 ODB[98281:70b] HMAC Hash Length: 41
2013-12-06 16:05:24.597 ODB[98281:70b] HMAC Hash Length: 41
2013-12-06 16:05:24.597 ODB[98281:70b] HMAC Hash Length: 41
2013-12-06 16:05:24.597 ODB[98281:70b] HMAC Hash Length: 41
2013-12-06 16:05:24.597 ODB[98281:70b] HMAC Hash Length: 41
2013-12-06 16:05:24.597 ODB[98281:70b] HMAC Hash Length: 41
2013-12-06 16:05:24.597 ODB[98281:70b] HMAC Hash Length: 41
2013-12-06 16:05:24.597 ODB[98281:70b] HMAC Hash Length: 41
2013-12-06 16:05:24.598 ODB[98281:70b] HMAC Hash Length: 41
2013-12-06 16:05:24.598 ODB[98281:70b] HMAC Hash Length: 41
2013-12-06 16:05:24.598 ODB[98281:70b] HMAC Hash Length: 41
2013-12-06 16:05:24.598 ODB[98281:70b] HMAC Hash Length: 41
2013-12-06 16:05:24.795 ODB[98281:70b] HMAC Hash Length: 20
2013-12-06 16:05:24.795 ODB[98281:70b] HMAC Hash Length: 41
2013-12-06 16:05:24.795 ODB[98281:70b] HMAC Hash Length: 41
2013-12-06 16:05:24.795 ODB[98281:70b] HMAC Hash Length: 41
2013-12-06 16:05:24.796 ODB[98281:70b] HMAC Hash Length: 41
2013-12-06 16:05:24.796 ODB[98281:70b] HMAC Hash Length: 41
2013-12-06 16:05:24.796 ODB[98281:70b] HMAC Hash Length: 41
2013-12-06 16:05:24.796 ODB[98281:70b] HMAC Hash Length: 24
2013-12-06 16:05:24.797 ODB[98281:70b] HMAC Hash Length: 41

这种hmac散列方法似乎已被普遍接受,因此我希望看到输出长度一致。我错过了什么?

1 个答案:

答案 0 :(得分:1)

如果我没记错的话,CCHmac以二进制形式输出结果,所以当这个函数完成时,输出[]应该总是用完全 20个字节填充。

回想一下,strlen()只是遍历内存,直到找到一个'null'字节,例如

int strlen(char *s)
{
  for(int n = 0; s[n] != 0; s++)
  {
    n++;
  }
  return n;
}

因此,如果输出[]中的一个字节为0,则NSLog语句将打印出小于20的值。否则,strlen()将继续搜索未定义的内存区域,直到它发生为在某处找到0的值。您将获得很大程度上无法预测的结果,这实际上可能会使您的程序崩溃。

相反,看起来您可能期望HMAC的十六进制字符串表示。要获得一个,你可以做类似的事情:

NSMutableString *hexOutput = [NSMutableString string];
for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) {
    [hexOutput appendFormat:@"%02x", output[i]];
}