【问题标题】:NSString from NSData always null来自 NSData 的 NSString 始终为空
【发布时间】:2013-11-29 16:27:13
【问题描述】:

我想用 HMAC SHA512 签署一个请求,但我似乎搞乱了 NSData 和 NSString 之间的编码和解码。我拼命想弄清楚哪里出了问题,但我似乎并没有做对。

伪代码:

function hmac_512(msg, sec) {
    sec = Base64Decode(sec);
    result = hmac(msg, sec, sha512);
    return Base64Encode(result);
}


secret = "7pgj8Dm6";
message = "Test\0Message";

result = hmac_512(message, secret);
if (result == "69H45OZkKcmR9LOszbajUUPGkGT8IqasGPAWqW/1stGC2Mex2qhIB6aDbuoy7eGfMsaZiU8Y0lO3mQxlsWNPrw==")
    print("Success!");
else
    printf("Error: %s", result);



我的实现:

+(void)doSomeMagic{

    NSString *message = @"Test\0Message";
    NSString *signedRequest = [self signRequestForParameterString:message];

    //checking against CORRECT (from JAVA equivalent) signed request 
    if ([signedRequest isEqualToString:@"69H45OZkKcmR9LOszbajUUPGkGT8IqasGPAWqW/1stGC2Mex2qhIB6aDbuoy7eGfMsaZiU8Y0lO3mQxlsWNPrw==" ])
        NSLog(@"Success!");
    else
        NSLog(@"Error!");
}

这里是签名方法:

+(NSString *)signRequestForParameterString:(NSString*)paramStr{

    NSString *secret = @"7pgj8Dm6";

    // secret is base64 encoded, so I decode it 
    NSData *decodedSecret = [secret base64DecodedData];
    NSString *decodedSecretString = [NSString stringWithUTF8String:[decodedSecret bytes]];

    NSData *data = [paramStr dataUsingEncoding:NSUTF8StringEncoding];
    NSString *dataString = [NSString stringWithUTF8String:[data bytes]];


    return [self generateHMACSHA512Hash:decodedSecretString data:dataString];

}

这里是哈希函数:

+(NSString *)generateHMACSHA512Hash:(NSString *)key data:(NSString *)data{


    const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding];
    const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];

    unsigned char cHMAC[CC_SHA512_DIGEST_LENGTH];

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

    NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC
                                          length:sizeof(cHMAC)];

    NSString *hash = [HMAC base64EncodedString];

    return hash;

} 

我很确定这是由于字符串的编码(decodedSecretString 和 dataString)。 decodedSecretString(解码后的base64)解码后用ASCII编码。但是,当我调用散列方法时,我再次将其编码为 ascii,这将导致 null 错误。现在一切都让我感到困惑。

【问题讨论】:

  • 有很多代码需要查看。你不能稍微调试一下,然后找出问题所在吗?
  • 如果您的密钥是 Base64 编码的,那么您应该对其进行解码并将解码后的 NSData 传递给您的 HMAC 函数。不要把它变回字符串。
  • 为什么要在+signRequestForParameterString: 中从一个NSString 到NSData 再返回到NSString,而它只是在HMAC 方法中转回一个字节数组?那有什么意义呢?只需将字符串传递给 HMAC 方法。而且您可能应该坚持使用 UTF8,而不是 ASCII,除非您知道您有 ASCII 文本并且服务器无法理解 UTF-8。

标签: objective-c macos sha hmac nsstringencoding


【解决方案1】:

您的密钥无法解码为有效的 UTF-8 字符串,Java 允许字符串中包含 NUL 字节,但是当您将“Test\0Message”转换为 C 字符串并使用 strlen 时,其长度为 4。

这样的事情应该可以工作:

+(NSString *)signRequestForParameterString:(NSString*)paramStr{
    NSString *secret = @"7pgj8Dm6";
    NSData *data = [paramStr dataUsingEncoding:NSUTF8StringEncoding];
    return [self generateHMACSHA512Hash:[secret base64DecodedData] data:data];
}

+(NSString *)generateHMACSHA512Hash:(NSData *)key data:(NSData *)data{
    unsigned char cHMAC[CC_SHA512_DIGEST_LENGTH];
    CCHmac(kCCHmacAlgSHA512, key.bytes, key.length, data.bytes, data.length, cHMAC);
    NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
    return [HMAC base64EncodedString];
}

【讨论】:

  • 难以置信!非常感谢!
【解决方案2】:

在执行 HMAC 或其他加密函数时,您应该先构建一些不处理字符串的基本方法/函数。然后,您可以创建包装方法,以方便的方式解码/编码字符串数据或摘要。

+ (NSData *)dataBySigningData:(NSData *)data withKey:(NSData *)key
{
  unsigned char cHMAC[CC_SHA512_DIGEST_LENGTH];
  CCHmac(kCCHmacAlgSHA512, [key bytes], [key length], [data bytes], [data lenght], cHMAC);
  return [[NSData alloc] initWithBytes:cHMAC length:CC_SHA512_DIGEST_LENGTH];
}

+ (NSData *)dataBySigningMessage:(NSString *)message withKey:(NSData *)key
{
  return [self dataBySigningData:[message dataUsingEncoding:NSUTF8StringEncoding]
                         withKey:[key dataUsingEncoding:NSUTF8StringEncoding]];
}

(注意:此代码未经测试,只是在文本编辑器中组合而成)

不必担心密钥或数据的字符串表示形式。然后你可以从那里去,例如获取摘要的 base64 编码。

加密函数不关心字符串或文本编码。他们关心字节。字符串(在 C 中,因为它们是空终止的)只是可以在数据中表示的内容的一个子集。因此,处理字符串将受到严重限制。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多