python中的Hashlib md5为某些unicode字符返回不正确的摘要?

2024-10-06 07:07:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在研究python和Java的MD5实现,遇到了一个困扰我的怪癖。在

下面的python脚本说明了这个问题:

# -*- coding: utf-8 -*-
import hashlib

def md5hash(x):
  m = hashlib.md5()
  m.update(x)
  return m.hexdigest()

print md5hash('\xdb')
print md5hash('Û')

输出:

^{pr2}$

我希望这两个摘要是等价的,因为Û应该与{}等价。我在Java中构建了一个等效的实现,以获得更多的洞察力:

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Test {
  public static void main(String[] args) throws Exception {
    MessageDigest m = MessageDigest.getInstance("MD5");

    m.update("\u00db".getBytes());
    System.out.println(bytesToHex(m.digest()));

    m.update("Û".getBytes());
    System.out.println(bytesToHex(m.digest()));
  }

  final protected static char[] hexArray = "0123456789abcdef".toCharArray();
  public static String bytesToHex(byte[] bytes) {
    char[] hexChars = new char[bytes.length * 2];
    for ( int j = 0; j < bytes.length; j++ ) {
      int v = bytes[j] & 0xFF;
      hexChars[j * 2] = hexArray[v >>> 4];
      hexChars[j * 2 + 1] = hexArray[v & 0x0F];
    }
    return new String(hexChars);
  }
}

输出:

31ecfb09f120720a55d96a2034f5d00b
31ecfb09f120720a55d96a2034f5d00b

Java的输出与预期一致。这使我相信md5hash('\xdb')输出的结果不正确,但我不确定我遗漏了什么。有什么想法吗?在


Tags: importstringbytesupdatestaticjavapublicmd5
2条回答

你的假设是不正确的。Python源代码的开头是:

# -*- coding: utf-8 -*-

在这种情况下,Û不是等价于\xdb;而是两个字节:

^{pr2}$

Python在这里是完全一致的:

>>> import hashlib
>>> hashlib.md5('\xc3\x9b').hexdigest()
'31ecfb09f120720a55d96a2034f5d00b'
>>> hashlib.md5('\xdb').hexdigest()
'98fd00d788afe2a5fa5e4f8e1666638b'

在Java中,您开始使用Unicode代码点,将其转换为UTF-8字节:

"\u00db".getBytes()

Python等价物将使用unicode字符串文本和\uhhhh或{}转义序列:

>>> u'\u00db'.encode('utf8')
'\xc3\x9b'
>>> u'\xdb'.encode('utf8')
'\xc3\x9b'

注意u前缀以生成unicode字符串。\xdb没有u前缀是一个字节串,而不是Unicode码位,只有当你将它解码为拉丁语1时,才会得到相同的Unicode字符串:

>>> '\xdb'.decode('latin1')
u'\xdb'
>>> '\xdb'.decode('latin1').encode('utf8')
'\xc3\x9b'

您可能想学习Python和Unicode;请参见:

为了完整起见:

I expected the two digests to be equivalent, given that Û ought to be equivalent to \xdb.

Û是UTF-8中的C3 9B,您似乎正在使用它(这是您声明的编码)。DB将是ISO-8859-1。在

>>> import hashlib
>>> hashlib.md5(b'\xc3\x9b').hexdigest()
'31ecfb09f120720a55d96a2034f5d00b'

塔达!在

相关问题 更多 >