【问题标题】:MD5 hashes from string don't match up [closed]字符串中的 MD5 哈希值不匹配 [关闭]
【发布时间】:2013-08-20 16:09:24
【问题描述】:

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

假设用户的密码是“cat”。如果我对此进行哈希处理,我会得到d077f244def8a70e5ea758bd8352fcd8。这等于我从 web 服务收到的哈希值。现在我知道创建 MD5 的代码是正确的。

但是,当密码是“çàt”时,我得到这个哈希值:727f8e931135b44b37eb147c8a7a56af。网络服务将这个哈希返回给我: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 编码,但没有一个返回正确的哈希值。

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

【问题讨论】:

  • 让我们在 Google 中输入d077f244def8a70e5ea758bd8352fcd8,你就会明白为什么密码永远不应该用 MD5 散列,尤其是没有盐的情况下。有一些密钥派生函数,如 BCrypt 或 PBKDF2,旨在散列密码。

标签: ios objective-c encoding hash md5


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    它确实与文本编码有关。请记住,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 带有 ACUTE 的拉丁小写字母 A),也可以表示为组合序列(U+0061 拉丁小写字母 A + U+0301 COMBINING ACUTE口音)。结果看起来相同(á 与 á),但大多数比较例程和哈希将被视为不同的字符串,除非首先进行规范化。

    【讨论】:

      【解决方案3】:

      在你必须导入通用加密库之前,你可以在 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;
      

      }

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

      【讨论】:

        猜你喜欢
        • 2011-09-12
        • 2014-05-19
        • 2017-06-04
        • 2020-12-08
        • 1970-01-01
        • 1970-01-01
        • 2019-10-10
        • 2019-12-20
        相关资源
        最近更新 更多