来自字符串的MD5哈希值不匹配

时间:2013-08-20 16:09:24

标签: ios objective-c encoding hash md5

我需要将密码转换为MD5哈希并将其与我从Web服务获得的MD5哈希进行比较。 如果这两者匹配,则用户可以登录。

假设用户的密码为“ cat ”。如果我做了哈希,我得到d077f244def8a70e5ea758bd8352fcd8。这等于我从webservice收到的哈希。现在我知道创建MD5的代码是正确的。

但是,当密码为“çàt”时,我会收到此哈希:727f8e931135b44b37eb147c8a7a56af。 webservice给了我这个哈希:f571ca52b4e3c5a6f49675deaea89cac

这就是问题所在。由于某些原因,这两个相同单词的哈希值不同,不知道这样的事情是否可能。 它只会在密码中出现重音或其他奇怪的字符时发生,所以我认为它与编码有关。

我尝试使用NSISOLatin1StringEncoding这样:

NSString *string = [NSString stringWithFormat:@"çàt"];

char converted[([string length] + 1)];
[string getCString:converted maxLength:([string length] + 1) encoding: NSISOLatin1StringEncoding];

NSString *converted_str = [NSString stringWithCString:converted encoding:NSISOLatin1StringEncoding];

在此处找到:Convert UTF-8 encoding to ISO 8859-1 encoding with NSString

但这也没有给我正确的哈希值。

我尝试了所有可能的NSString编码,但没有一个人返回正确的哈希值。

那我该怎么办?转换编码的代码有问题吗?或者它可能与编码没有任何关系(因为尝试其他编码不起作用)?

3 个答案:

答案 0 :(得分:1)

我会说727 ......你得到的是正确的,这也是md5命令行工具给出的。所以这是你的服务器部分坏了 - 正如你已经说过的,它可能只是一些错误的编码 - 在向服务器传输文本时要小心。

答案 1 :(得分:1)

它与文本编码有关。请记住,MD5哈希工作在字节上,而不是在字符上。因此,您输入文本的编码很重要!

以下是散列到您所看到的结果的字节序列:

d077f244def8a70e5ea758bd8352fcd8 = 63 61 74       ("cat", ASCII)

727f8e931135b44b37eb147c8a7a56af = c3 a7 c3 a0 74 ("çát", UTF-8 NFC)

f571ca52b4e3c5a6f49675deaea89cac = e7 e0 74       ("çát", ISO8859-1)

在处理此问题时,请记住以下非常重要的一点:

  • 并非所有字符都可以在ISO8859-1中表示。它仅限于西欧语言中的字符。
  • 即使在UTF-8中,也可以有多个相同字符的表示形式。最值得注意的是,诸如“á”之类的重音字符可以表示为单个预组合字符(U + 00E1 LATIN SMALL LETTER A WITH ACUTE),或者表示为组合序列(U + 0061 LATIN SMALL LETTER A + U + 0301 COMBINING ACUTE口音)。结果看起来相同(á与á),但大多数比较例程以及哈希将被视为不同的字符串,除非首先进行标准化。

答案 2 :(得分:0)

使用此方法,在必须导入公共加密库之前,在Objective-c中返回md5哈希字符串

#import <CommonCrypto/CommonDigest.h>

-(NSString*)md5HexDigest:(NSString*)input {
const char* str = [input UTF8String];
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5(str, strlen(str), result);

NSMutableString *ret = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH*2];
for(int i = 0; i<CC_MD5_DIGEST_LENGTH; i++) {
    [ret appendFormat:@"%02x",result[i]];
}
return ret;

}

然后确保您在两个部分,您的应用和您的网络服务中使用相同的编码系统,我建议使用“UTF-8”,但如果您使用“latin 1”,那么在您的网络服务中,您应该使用“iso-850-1”