簡體   English   中英

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

[英]Hashlib md5 in python returning incorrect digests for some unicode characters?

我一直在研究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('Û')

輸出:

98fd00d788afe2a5fa5e4f8e1666638b
31ecfb09f120720a55d96a2034f5d00b

考慮到Û應該等效於\\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);
  }
}

輸出:

31ecfb09f120720a55d96a2034f5d00b
31ecfb09f120720a55d96a2034f5d00b

正如預期的那樣,Java的輸出是一致的。 這使我相信md5hash('\\xdb')輸出的結果不正確,但是我不確定丟失了什么。 有什么想法嗎?

您的假設是不正確的。 您使用以下代碼啟動了Python源代碼:

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

Û 等同於\\xdb在這種情況下; 而是兩個字節:

>>> u'Û'.encode('utf8')
'\xc3\x9b'

Python在這里是完全一致的:

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

在Java中,您改用Unicode代碼點開始,將其轉換為UTF-8字節:

"\u00db".getBytes()

Python的等價是使用一個unicode字符串文字,無論是\\uhhhh\\xhh轉義序列:

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

注意u前綴以生成unicode字符串。 不帶u前綴的\\xdb是一個字節字符串 ,而不是Unicode代碼點,只有將其解碼為Latin 1時 ,您才會獲得相同的Unicode字符串:

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

您可能想學習Python和Unicode。 看到:

為了完整起見:

考慮到Û應該等效於\\xdb ,我希望這兩個摘要等效。

Û是您似乎正在使用的UTF-8中的C3 9B (它是您聲明的編碼)。 DB將為ISO-8859-1。

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

-

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM