Objective-C中HMAC SHA1实现的问题

时间:2013-04-12 16:13:06

标签: ios objective-c cocoa hmacsha1 commoncrypto

我正在尝试使用HMAC-SHA1算法为休息请求创建base64签名。我专门使用SinglePlatform API,步骤如下:

  1. 删除请求的域部分,只留下路径和查询:/ locations / haru-7?client = YOUR_CLIENT_ID
  2. 检索您的私钥,该私钥在经过修改的Base64中编码,并使用HMAC-SHA1算法在上面签名。您可能需要将签名密钥解码为其原始二进制格式。在许多加密库中,生成的签名将采用二进制格式。
  3. 使用修改后的Base64 for URL对生成的二进制签名进行编码,以将此签名转换为可在URL中传递的内容。 使用sigparameter将此签名附加到URL:
  4. 我目前的实施如下:

        // Convert a modified Base64 key into Base64
    NSString *modifiedKey = [SIGNING_KEY stringByReplacingOccurrencesOfString:@"-" withString:@"+"];
    modifiedKey = [modifiedKey stringByReplacingOccurrencesOfString:@"_" withString:@"/"];
    
    // Decode the Base64 key
    NSData *key = [NSData dataFromBase64String:modifiedKey];
    
    // Construct a url with params
    NSString *data = [NSString stringWithFormat:@"/locations/%@?client=%@", _id, CLIENT_ID];
    
    // Convert key and data to c chars
    const char *keyBytes = [key bytes];
    const char *baseStringBytes = [data cStringUsingEncoding:NSUTF8StringEncoding];
    
    unsigned char digestBytes[CC_SHA1_DIGEST_LENGTH];
    
    CCHmacContext ctx;
    CCHmacInit(&ctx, kCCHmacAlgSHA1, keyBytes, strlen(keyBytes));
    CCHmacUpdate(&ctx, baseStringBytes, strlen(baseStringBytes));
    CCHmacFinal(&ctx, digestBytes);
    
    NSData *digestData = [NSData dataWithBytes:digestBytes length:CC_SHA1_DIGEST_LENGTH];
    
    // Reconvert the into Base64 modified 
    NSString *signingKey = [digestData base64EncodedString];
    signingKey = [signingKey stringByReplacingOccurrencesOfString:@"+" withString:@"-"];
    signingKey = [signingKey stringByReplacingOccurrencesOfString:@"/" withString:@"_"];
    
    if ( [data hasSuffix:@"="] ) {
        [signingKey substringToIndex:[hassigningKeyh length]-1];
    }
    
    NSLog(@"Signing Key: %@", signingKey);
    

    我最初收到的签名密钥是修改后的Base64,这就是我要替换 - + _ /字符的原因。此实现已返回正确的签名密钥,但不一致。

    在将Objective-C转换为C时,我做了一些明显的错误吗?有没有更好的方法来解决这个问题?

    我的应用程序正在使用ARC。

1 个答案:

答案 0 :(得分:1)

问题在于我是确定数据长度的C方法:

CCHmacContext ctx;
CCHmacInit(&ctx, kCCHmacAlgSHA1, keyBytes, strlen(keyBytes));
CCHmacUpdate(&ctx, baseStringBytes, strlen(baseStringBytes));
CCHmacFinal(&ctx, digestBytes);

当我使用NSString / NSData长度方法时,它一直工作:

CCHmacContext ctx;
CCHmacInit(&ctx, kCCHmacAlgSHA1, keyBytes, [key length]);
CCHmacUpdate(&ctx, baseStringBytes, [data length]);
CCHmacFinal(&ctx, digestBytes);

修改
正如评论中Ivo Beckers所提到的,这也可以写成一行:

CCHmac(kCCHmacAlgSHA1, keyBytes, strlen(keyBytes), baseStringBytes, strlen(baseStringBytes), digestBytes);