雜湊函數與 HMAC
🔥 Vibe Prompt
「比較 SHA-256、SHA-3、SHA-512 的雜湊速度。實作 HMAC 進行 API 認證。」
import hashlib, hmac, time
def bench_hash(name, data, func):
start = time.time()
for _ in range(100000):
func(data).hexdigest()
elapsed = time.time() - start
print(f"{name}: {elapsed:.2f}s ({100000/elapsed:.0f} 次/秒)")
data = b"Hello, Security!" * 1000
bench_hash("SHA-256", data, hashlib.sha256)
bench_hash("SHA-512", data, hashlib.sha512)
bench_hash("SHA-3-256", data, hashlib.sha3_256)
bench_hash("BLAKE2b", data, hashlib.blake2b)
# 用 HMAC 做 API 認證
secret_key = b"api-secret-key-12345"
message = b"GET /api/orders 1700000000"
hmac_sig = hmac.new(secret_key, message, hashlib.sha256).hexdigest()
print(f"\nHMAC-SHA256: {hmac_sig}")
# 驗證
expected = hmac.new(secret_key, message, hashlib.sha256).hexdigest()
print(f"驗證結果: {hmac.compare_digest(hmac_sig, expected)}")
應用場景
- 密碼儲存(加鹽雜湊)
- 檔案完整性(檢查碼)
- API 認證(HMAC)
- 區塊鏈(梅克爾樹)
- 數位簽章
關鍵要點
常見雜湊演算法比較
| 演算法 | 輸出長度 | 安全性 | 用途 | |:------:|:--------:|:------:|------| | MD5 | 128 bits | ❌ 不安全 | 僅用於檔案完整性(非安全) | | SHA-1 | 160 bits | ❌ 不安全 | 已淘汰,不應使用 | | SHA-256 | 256 bits | ✅ 安全 | 數位簽章、區塊鏈、憑證 | | SHA-3 | 可變 | ✅ 安全 | 新一代標準 | | Bcrypt | 可變 | ✅ 安全 | 密碼儲存(內建 Salt + Work Factor) | | Argon2 | 可變 | ✅ 最安全 | 密碼儲存首選(2015 年冠軍) |
為什麼需要 HMAC?
單純的 SHA-256 容易受到 長度擴充攻擊 (Length Extension Attack)。HMAC (Hash-based Message Authentication Code) 透過加入金鑰來解決這個問題,確保資料不會被篡改。
Python 實作
import hashlib
import hmac
# SHA-256 雜湊
data = b"Hello, World!"
print(hashlib.sha256(data).hexdigest())
# HMAC-SHA256(需要金鑰)
key = b"my-secret-key"
hmac_result = hmac.new(key, data, hashlib.sha256).hexdigest()
print(hmac_result)
# Bcrypt(密碼儲存)
import bcrypt
password = b"my-password"
hashed = bcrypt.hashpw(password, bcrypt.gensalt(rounds=12))
print(bcrypt.checkpw(password, hashed)) # True
雜湊:密碼學中的指紋
雜湊函數(Hash Function)是密碼學中最被廣泛使用的工具之一。它把任意長度的輸入轉換成固定長度的輸出——而且這個過程不可逆。
雜湊函數的必要特性
| 特性 | 說明 | 違反的後果 | |:----|:----|:---------| | 單向性 | 從 hash 無法還原原文 | 密碼可以被破解 | | 碰撞抵抗 | 不同輸入不該產生相同 hash | 兩個不同文件有相同簽章 | | 雪崩效應 | 輸入差一點點,hash 完全不同 | 無法區分類似輸入 | | 固定長度 | 無論輸入多大,輸出長度固定 | 無法預測儲存空間 |
為什麼不直接用 SHA-256 存密碼?
因為使用者的密碼通常不夠亂。攻擊者可以預先計算常見密碼的 hash(彩虹表),然後比對就能知道你的密碼。
正確做法:加鹽(Salt)——每個使用者的密碼都加上一段隨機字串再 hash。
import hashlib, os
# 每個使用者產生不同的鹽
salt = os.urandom(32) # 32 bytes 隨機
hashed = hashlib.pbkdf2_hmac(
'sha256',
password.encode('utf-8'),
salt,
100000 # 迭代次數,越慢越安全
)
下一章預告:TLS 1.3
雜湊函數是安全通訊的基礎。下一章的 TLS 1.3 將告訴你雜湊在 HTTPS 中扮演的角色——憑證驗證、金鑰交換、訊息完整性。