這裡介紹如何使用 Python 的 hashlib 模組計算資料的 MD5 與 SHA 雜湊值。

Python 內建的 hashlib 模組可以用來計算資料的各種雜湊值,其中 md5sha1sha224sha256sha384sha512 這幾種演算法是任何平台都有支援的,除此之外的演算法就要看平台本身的 OpenSSL 函式庫而定。

計算 MD5 雜湊值

若要計算資料的 MD5 雜湊值,可以使用 hashlib 模組的 md5() 建立一個 MD5 演算法的物件,再將資料輸入其中計算雜湊值,以下是在 Python 2 之下的實作版本:

#!/usr/bin/python
# -*- coding: utf-8 -*-

# 引入 hashlib 模組
import hashlib

# 建立 MD5 物件
m = hashlib.md5()

# 要計算 MD5 雜湊值的資料
data = "G. T. Wang"

# 更新 MD5 雜湊值
m.update(data)

# 取得 MD5 雜湊值
h = m.hexdigest()
print(h)
6871bb74e606dc7b4988b643e4870a8d

上面這段程式碼若在 Python 3 中執行,會產生類似這樣的錯誤訊息:

TypeError: Unicode-objects must be encoded before hashing

解決的方法是先讓資料經過編碼之後,再放進 hashlib 計算雜湊:

#!/usr/bin/python3
import hashlib
m = hashlib.md5()
data = "G. T. Wang"

# 先將資料編碼,再更新 MD5 雜湊值
m.update(data.encode("utf-8"))

h = m.hexdigest()
print(h)
6871bb74e606dc7b4988b643e4870a8d

計算檔案的 MD5 雜湊值

如果要計算一個檔案的 MD5 雜湊值,可以將檔案內容讀取之後,再放進 MD5 演算法的物件來計算雜湊值:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import hashlib

# 輸入檔案名稱
filename = "my_data.txt"

m = hashlib.md5()

# 讀取檔案內容,計算 MD5 雜湊值
with open(filename, "rb") as f:
  buf = f.read()
  m.update(buf)

h = m.hexdigest()
print(h)

如果檔案比較大的話,可以分批次讀取,每次讀取一部分的內容,使用 update 來更新 MD5 雜湊值,這樣程式的效率會比較好:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import hashlib

filename = "my_data.txt"
m = hashlib.md5()

with open(filename, "rb") as f:
  # 分批讀取檔案內容,計算 MD5 雜湊值
  for chunk in iter(lambda: f.read(4096), b""):
    m.update(chunk)

h = m.hexdigest()
print(h)

這樣計算出來的 MD5 雜湊值應該會跟 md5sum 指令所算出來的值相同:

md5sum my_data.txt

計算 SHA 雜湊值

若要計算 SHA 類型的雜湊值,只要把演算法更改一下即可,以下是計算 SHA1 雜湊值的範例:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import hashlib

# 建立 SHA1 物件
s = hashlib.sha1()

data = "G. T. Wang"
s.update(data)
h = s.hexdigest()
print(h)
baa7cc8598a4753c5d71d07e6cc6242ef0994d63

其他雜湊演算法

我們可以透過 hashlib.algorithms_available 得知在目前的平台上,hashlib 所支援的所有雜湊演算法:

# 可用的雜湊演算法
print(hashlib.algorithms_available)
{'sha256', 'MD5', 'MD4', 'sha384', 'dsaWithSHA', 'SHA224', 'ripemd160', 'SHA512', 'SHA', 'sha', 'SHA384', 'md5', 'sha512', 'DSA', 'RIPEMD160', 'md4', 'whirlpool', 'SHA256', 'dsaEncryption', 'sha1', 'ecdsa-with-SHA1', 'DSA-SHA', 'SHA1', 'sha224'}

以上這些演算法雖然很多,但只限於目前的系統使用,如果要發展跨平台的程式,應該要以跨平台通用的雜湊演算法為主,這些跨平台的演算法可以透過 hashlib.algorithms_guaranteed 查詢:

# 跨平台通用的雜湊演算法
print(hashlib.algorithms_guaranteed)
{'sha256', 'sha384', 'sha1', 'md5', 'sha512', 'sha224'}

參考資料:Python 官方文件