2013-08-20 73 views
0

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

假设用户的密码是'cat'。如果我做了一个哈希,我得到了d077f244def8a70e5ea758bd8352fcd8。这等于我从web服务收到的散列。现在我知道创建MD5的代码是正确的。

但是,当密码是'çàt',我得到这个哈希:727f8e931135b44b37eb147c8a7a56af。 web服务给我回这个哈希: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编码,但没有一个em返回正确的散列。

那么我能做些什么呢。用于转换编码的代码有问题吗?或者,它可能与编码没有任何关系(因为尝试其他编码不起作用)?

+0

让我们在Google中输入'd077f244def8a70e5ea758bd8352fcd8',你就会明白为什么密码不能用MD5散列,特别是没有盐。有像BCrypt或PBKDF2这样的密钥派生函数用于哈希密码。 – martinstoeckli

回答

1

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

0

采用此方法返回在Objective-C的MD5散列字符串,前u必须导入公共的密码库

#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; 

}

然后确保你使用的是相同的编码系统在这两个部分,您的应用程序和您的Web服务,我建议使用“UTF-8”,但如果您使用的是“拉丁语1”,那么在您的Web服务中,您应该使用“iso-850-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小字母A WITH ACUTE),或者作为组合序列(U + 0061 LATIN小字母A + U + 0301组合急性口音)。结果看起来相同(á对á),但除非首先进行标准化,否则大多数比较例程以及哈希将被视为不同的字符串。