雜湊函數與 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 中扮演的角色——憑證驗證、金鑰交換、訊息完整性。

解鎖完整教學內容

本章為付費內容。加入專案即可解鎖超過 5000 字的深度解析,包含 10 個以上神級 Prompt 與真實 Source Code 範例!