HOWTO · Python
Python 校驗和
學習如何使用 Python 的 hashlib 產生檔案校驗和,並與可信的 SHA-256 摘要比對。
本頁內容
檔案校驗和是根據檔案位元組計算出的精簡摘要。下載檔案後,你可以計算摘要,並與透過可信管道發布的摘要比對。比對相符有助於偵測意外變更或資料損毀,但這本身無法證明檔案由誰建立:若攻擊者能同時替換檔案及其參考摘要,就能讓兩者相符。
Python 的 hashlib 模組提供標準雜湊演算法。這個過程具有決定性:相同的位元組與演算法會產生相同摘要,而即使只變更一個位元組,結果通常也會不同。校驗和描述的是位元組,而非檔名或檔案格式。
檔案校驗和能告訴你什麼
校驗和可以幫助你確認檔案副本是否仍含有預期內容。預期值必須來自你信任的來源,例如經過獨立驗證的發布頁面。若兩個值都是從同一個不可信位置下載的,比對它們並不能提供太多保障。若涉及安全性判斷,請使用現代密碼學雜湊,例如 SHA-256,並另外驗證參考值的來源。
使用 hashlib 產生校驗和
以二進位模式開啟檔案,讓 Python 雜湊檔案的原始位元組,不進行文字解碼或換行轉換。分塊讀取檔案,並將每個區塊傳給雜湊物件的 update() 方法。即使檔案遠大於可用記憶體,這樣也能將記憶體用量維持在有限範圍。hexdigest() 會傳回可列印的十六進位文字;digest() 則會以打包後的位元組傳回相同摘要。
請執行以下範例:
本節中的程式碼以及顯示的標籤或輸出仍為英文。
import hashlib
from pathlib import Path
from tempfile import TemporaryDirectory
def sha256_file(path):
digest = hashlib.sha256()
with open(path, "rb") as file:
for chunk in iter(lambda: file.read(64 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
with TemporaryDirectory() as directory:
path = Path(directory) / "sample.bin"
path.write_bytes(b"abc")
expected = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
actual = sha256_file(path)
print(f"SHA-256: {actual}")
print(f"Matches trusted value: {actual == expected}")
SHA-256: ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
Matches trusted value: True
這段程式碼會建立一個小型範例檔,因此可以照原樣執行;在自己的程式中,請將 path 改成下載檔案的路徑。若要處理下載的檔案,請將 path 設為該檔案的位置,再把算出的摘要與該檔案的可信參考值比對。
比對可信校驗和來驗證檔案
請獨立儲存或取得預期摘要,再與 sha256_file 傳回的值比對。範例中的布林值比較會在兩個十六進位字串相符時得到真。若結果為假,表示檔案與該參考值不符;檔案可能已損毀、遭到刻意修改,或搭配了錯誤的參考值。請重新下載或調查來源,不要把比對不符當成特定原因的證明。
若工作流程涉及安全性,請只依照發布者說明的格式正規化預期字串,再比對完整摘要。若有完整摘要可用,請勿只比對其中一小段。比對相符表示檔案與預期摘要所代表的可信位元組相符;除非參考值本身經過驗證,否則這並不能驗證發布者的身分。
處理大型檔案與常見錯誤
分塊讀取可避免將整個檔案載入記憶體。只要每個位元組都依序讀取一次,區塊大小只會影響 I/O 效率,不會改變摘要結果。二進位模式很重要,因為文字模式可能會解碼資料或轉換換行字元。請像 with 陳述式所示,只在讀取期間保持檔案開啟。
對於非常大的檔案,請避免使用 file.read() 一次讀取所有位元組。也請確認路徑指向你要驗證的檔案,並確認計算參考值時使用的雜湊演算法與本機使用的演算法相同。即使檔案內容沒有變動,拼字或演算法不同也會產生不同字串。若計算期間檔案有所變動,摘要可能會混合檔案在不同時間的內容;若其他程序可能正在寫入檔案,請改用穩定的副本進行驗證。
選擇雜湊演算法並了解其限制
若可信的發布者提供 SHA-256 參考值,可使用 SHA-256 計算一般用途的檔案摘要。你可以透過 hashlib.sha256() 使用這個演算法。某些舊範例與相容性流程仍會使用 MD5,但它容易受到碰撞攻擊,不適用於安全性要求高的完整性檢查。請勿使用 MD5 來確認真實性,或防範蓄意攻擊者。
校驗和與密碼雜湊也不同:快速摘要適合用來比對檔案,密碼則需要專用且加鹽的密碼雜湊方案。無論使用哪種方式,摘要只能回答位元組是否與某個參考值相符。是否值得信任,取決於參考值的取得方式與保護方式。