1. 程式人生 > >使用python2與python3中md5的區別以及需要注意的地方

使用python2與python3中md5的區別以及需要注意的地方

你可能不知道的是,有很多字元,使用python2和python3的md5加密出來的結果是不一樣的

 

 

# python2.7

zfc = "xxx" + chr(163) + "fj"

cd = hashlib.md5(zfc).hexdigest()

print cd # ea25a328180680aab82b2ef8c456b4ce

 

# python3.6

zfc = "xxx" + chr(163) + "fj"

cd = hashlib.md5(zfc.encode("utf-8")).hexdigest()

print(cd) # b517e074034d1913b706829a1b9d1b67

按程式碼差異來將,就是在python3中需要對字串進行 encode 操作,如果沒有則會報錯:

 

cd = hashlib.md5(zfc).hexdigest()

TypeError: Unicode-objects must be encoded before hashing

這是因為加密時需要將字串轉化為 bytes 型別,3預設編碼是 utf-8 .所以我用utf-8進行解碼.

分析

如果字串中沒有 chr(163)

 ,那麼兩個版本結果是一致的,也就是說問題出在這個chr(163)中:

 

# python2.7

>>> chr(163)

'\xa3'

 

# python3.6

>>> chr(163)

'\xa3'

在這裡說明通過 chr 得到的結果是一致的, 將它轉為 bytes 型別看看:

 

# python2.7

>>> bytes(chr(163))

'\xa3'

 

# python3.6

>>> chr(163).encode()

b'\xc2\xa3'

python3中,在 num<128 的時候,使用 chr(num).encode('utf-8') 得到的是 一個 字元的ascii十六進位制,而 num>128 的時候,使用 chr(num).encode('utf-8') 得到的是 兩個 位元組的ascii十六進位制.

解決
改用 latin1 編碼進行解碼:

 

# python3.6

zfc = "xxx" + chr(163) + "fj"

cd = hashlib.md5(zfc.encode("latin1")).hexdigest()

print(cd)  # ea25a328180680aab82b2ef8c456b4ce

額外
為什麼是 latin1 編碼呢.答案還是挺有意思的.

先說chr函式,通過 help(chr) 可以檢視:

 

chr(...)

  chr(i) -> Unicode character

  Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff.

意思是它返回Unicode編碼中指定位置的一個字元.python3內部也是用Unicode表示左右字元,即str型別.而通過encode後會編碼成 bytes 型別.

ascii編碼中每個字元編碼是一個byte,但只有1-127. 超過的部分128-255則屬於 Extended ASCII ,python3 中預設的ascii中不包含這部分,所以如果執行 chr(163).encode("ascii") 就會報錯 'ascii' codec can't encode character '\xa3' in position 3: ordinal not in range(128)

因此需要一個含有128-255中的部分字元的編碼,且採用1個Byte固定大小編碼,比如ISO 8859-1,也就是 latin1.當然還有其他編碼如cp1252也包含這些字元的.