iel*_*shi 0 python unicode hash md5
我一直在玩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('Û')
Run Code Online (Sandbox Code Playgroud)
输出:
98fd00d788afe2a5fa5e4f8e1666638b
31ecfb09f120720a55d96a2034f5d00b
Run Code Online (Sandbox Code Playgroud)
我预计两个摘要是等价的,因为它Û应该相当于\xdb.我在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);
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
31ecfb09f120720a55d96a2034f5d00b
31ecfb09f120720a55d96a2034f5d00b
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,Java的输出是一致的.这让我相信md5hash('\xdb')输出的结果不正确,但我不确定我错过了什么.有什么想法吗?
你的假设是不正确的.您使用以下命令启动了Python源代码:
# -*- coding: utf-8 -*-
Run Code Online (Sandbox Code Playgroud)
Û是不等同于\xdb在这种情况下; 它改为两个字节:
>>> u'Û'.encode('utf8')
'\xc3\x9b'
Run Code Online (Sandbox Code Playgroud)
Python在这里完全一致:
>>> import hashlib
>>> hashlib.md5('\xc3\x9b').hexdigest()
'31ecfb09f120720a55d96a2034f5d00b'
>>> hashlib.md5('\xdb').hexdigest()
'98fd00d788afe2a5fa5e4f8e1666638b'
Run Code Online (Sandbox Code Playgroud)
在Java中,您首先使用Unicode代码点,将其转换为UTF-8字节:
"\u00db".getBytes()
Run Code Online (Sandbox Code Playgroud)
Python的等价物是使用unicode字符串文字和一个\uhhhh或\xhh转义序列:
>>> u'\u00db'.encode('utf8')
'\xc3\x9b'
>>> u'\xdb'.encode('utf8')
'\xc3\x9b'
Run Code Online (Sandbox Code Playgroud)
注意u生成unicode字符串的前缀.\xdb没有u前缀的是字节字符串,而不是Unicode代码点,并且只有当您将其解码为Latin 1才能获得相同的Unicode字符串:
>>> '\xdb'.decode('latin1')
u'\xdb'
>>> '\xdb'.decode('latin1').encode('utf8')
'\xc3\x9b'
Run Code Online (Sandbox Code Playgroud)
您可能想要研究Python和Unicode; 看到:
Ned Batchelder的实用Unicode
为了完整起见:
| 归档时间: |
|
| 查看次数: |
2325 次 |
| 最近记录: |