【问题标题】:MD5 in Object-C not matching resultsObject-C 中的 MD5 与结果不匹配
【发布时间】:2013-02-25 09:42:51
【问题描述】:

我尝试使用 md5 散列一个字符串(十六进制)。然而,输出字符串与我在 python 或 javascript (node.js) 中创建的类似输出不匹配。

输入字符串:

NSString *input = @"001856413a840871624d6c6f553885b5b16fae345c6bdd44afb26141483bff629df47dbd9ad0";


- (NSString *)md5:(NSString *)input {
// b2b22e766b849b8eb41b22ae85dc49b1
unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH];
const char *cStr = [input UTF8String];
CC_MD5_CTX ctx;
CC_MD5_Init(&ctx);
CC_MD5_Update(&ctx, cStr, [input length]);
CC_MD5_Final(md5Buffer, &ctx);

NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
    [output appendFormat:@"%02x",md5Buffer[i]];

return output;

}

在 python 中我会这样做:

binaryCredentialString = binascii.unhexlify(input)
# Now MD5 hash the binary string    
m = hashlib.md5()
m.update(binaryCredentialString)
# Hex encode the hash to obtain the final credential string
credential = m.hexdigest()

Python 给了我正确的 md5 输出,object-C 没有。这是为什么呢?

非常感谢任何帮助 - 帕斯卡

【问题讨论】:

  • 附带说明:如果您只有一个数据缓冲区要输入哈希,只需使用一步CC_MD5 而不是单独的InitUpdateFinal 函数。

标签: python objective-c hash md5


【解决方案1】:

在 Python 中,您将十六进制解码回二进制,但在 Objective-C 中,您不是。将您的字符串解码为NSMutableData 实例,然后将[data bytes](和[data length])提供给摘要函数。

【讨论】:

  • 嗨dreamlax,感谢您的回复。我已经试过了,它给了我同样的哈希!?!
  • 您是否将十六进制解码或只是将字符串的字符解码为NSData 对象?
  • 不,我没有解码!在 object-c 中执行此操作的最佳方法是什么?
【解决方案2】:

这和dreamlax的回答基本一样,但是你显然没看懂他的回答。希望我能帮上忙(但如果是这样,你应该接受他的回答)。

您的问题是您正在对 76 个字符的字符串 @"001856413a840871624d6c6f553885b5b16fae345c6bdd44afb26141483bff629df47dbd9ad0" 进行 MD5,而不是字符串编码的 38 字节二进制数据。

在 Python 中,您输入 md5 函数的内容是这样的:

binaryCredentialString = binascii.unhexlify(input)

但在 ObjC 中,是这样的:

const char *cStr = [input UTF8String];

所以,你需要一个等价的unhexlify

我将通过类别添加方法 -(NSString *)hexlifyNSData-(NSData *)unhexlifyNSString 来处理这个问题。然后你就可以写这段代码,和 Python 一样可读:

- (NSString *)md5:(NSString *)input {
    NSData *binaryCredentialString = [input unhexlify];
    NSMutableData *result = [NSMutableData dataWithLength:CC_MD5_DIGEST_LENGTH];
    CC_MD5([binaryCredentialString bytes],
           [binaryCredentialString length],
           [m mutableBytes]);
    return [result hexlify];
}

那么,您如何编写这些类别?使用你的代码,以及它的反面,像这样(未经测试,需要一些验证和错误处理,但你应该明白):

@implementation NSData(hexlify)
- (NSString *)hexlify {
    unsigned char *buf = [self bytes];
    size_t len = [self length];
    NSMutableString *output = [NSMutableString stringWithCapacity:len * 2];
    for(int i = 0; i < len; i++)
        [output appendFormat:@"%02x",buf[i]];
    return [NSData dataWithData:output];
}
@end

static unsigned char unhexchar(char c) {
    if (c <= '9') return c - '0';
    if (c <= 'F') return c - 'A' + 10;
    return c - 'a' + 10;
}

@implementation NSString(hexlify)
- (NSData *)unhexlify {
    const char *cStr = [self UTF8String];
    size_t len = [self length];
    NSMutableData *output = [NSMutableData dataWithLength:len / 2];
    unsigned char *buf = [output mutableBytes];
    for(int i = 0; i < len / 2; i++)
        buf[i] = unhexchar(cStr[i*2]) * 16 + unhexchar(cStr[i*2+1]);
    return [NSString stringWithString:output];
}
@end

但我确信通过一些搜索,您可以找到这两种方法的干净、经过测试和优化的实现,而不是自己编写它们。例如,请参阅this questionthis one 以及 SO 的其他各种人员。

【讨论】:

  • 你得到 +1 是因为我懒得寻找 unhexlify 方法。
  • @dreamlax:我参与过的每个 ObjC 项目,我要做的第一件事就是添加这两个类别。你会认为我要么找到准备好的东西,要么创建一个完善的版本并自己在 GitHub 上签入,但不,每次,我都会做同样的搜索。所以我已经很擅长了。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-17
  • 1970-01-01
  • 1970-01-01
  • 2014-05-19
  • 2018-03-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多