Obj-C中的MD5结果不匹配
我尝试用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输出是正确的,而Objective-C却不对。这是为什么呢?
任何帮助都非常感谢!
- Pascal
2 个回答
这基本上和dreamlax的回答是一样的,但你似乎没有理解他的意思。希望我能帮到你(不过如果能帮到你,你应该接受他的回答)。
你的问题在于,你对这个76个字符的字符串 @"001856413a840871624d6c6f553885b5b16fae345c6bdd44afb26141483bff629df47dbd9ad0"
做了MD5加密,而不是对这个字符串所表示的38字节的二进制数据进行加密。
在Python中,你传给 md5
函数的是这个:
binaryCredentialString = binascii.unhexlify(input)
但在ObjC中,你传给它的是这个:
const char *cStr = [input UTF8String];
所以,你需要一个和 unhexlify
功能相同的东西。
我会通过给 NSData
添加 -(NSString *)hexlify
方法,以及给 NSString
添加 -(NSData *)unhexlify
方法来处理这个问题,使用类别来实现。这样你就可以写出和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
不过我相信只要稍微搜索一下,你就能找到这两个方法的干净、经过测试和优化的实现,而不必自己写。例如,可以看看 这个问题、这个问题,以及Stack Overflow上的其他各种问题。
在Python中,你是把十六进制的字符串转换回二进制的,但在Objective-C中你没有这么做。你需要把你的字符串解码成一个NSMutableData
的实例,然后把[data bytes]
(和[data length]
)传给摘要函数。