加密這個主題很容易讓工程師陷入「我不是密碼學家,不需要懂」的迴避,然後在實作裡犯下「用 MD5 存密碼」或「HTTPS 下還在 base64 encode 敏感資料當加密」這類錯誤。
不需要懂數學,但要知道四種基本機制各解什麼問題。
對稱加密(Symmetric Encryption)
同一把 key,加密和解密都用它。
明文 + Key → [AES-256] → 密文
密文 + Key → [AES-256] → 明文
優點:速度快,適合加密大量資料。
缺點:key 要怎麼安全地傳給對方?在傳輸過程中如果 key 被截走就全完了。
常見算法:AES-128 / AES-256(現代標準),DES / 3DES(過時,不用)。
用途:加密靜態資料(database encryption、disk encryption)、TLS 建立連線後的資料傳輸。
非對稱加密(Asymmetric Encryption)
公鑰加密,私鑰解密(或反向用來 signing)。
明文 + 公鑰 → [RSA] → 密文 (任何人都能加密)
密文 + 私鑰 → [RSA] → 明文 (只有私鑰持有者能解密)
優點:解決金鑰分發問題——公鑰可以公開,不怕被截。
缺點:慢,不適合加密大量資料。
常見算法:RSA-2048 / RSA-4096、ECC(Elliptic Curve Cryptography,同等安全性但 key 更短,適合資源受限環境)。
用途:TLS 握手時交換 session key、SSH key authentication、憑證體系(PKI)。
TLS 的組合:TLS 不是純粹用非對稱加密傳資料(太慢),而是用非對稱加密安全地交換一個對稱加密的 session key,之後資料傳輸用對稱加密——兩種的優點都用到。
Hash(雜湊)
單向函式,輸入任意長度資料,輸出固定長度的摘要。無法從摘要反推輸入。
"password123" → [SHA-256] → "ef92b778..."
"password124" → [SHA-256] → "c15f3b12..." (完全不同)
特性:確定性(同樣輸入永遠同樣輸出)、雪崩效應(輸入微小改動,輸出完全不同)、不可逆。
常見算法:
- SHA-256 / SHA-3:現代標準,完整性驗證用
- bcrypt / Argon2 / scrypt:密碼 hash 專用,內建 salt + 計算成本(慢是特性,防暴力破解)
- MD5 / SHA-1:已被破解(碰撞攻擊),只有在非安全場景(checksum)才勉強用
密碼儲存的正確做法:
# 錯誤:MD5 或 SHA-256 直接 hash
hash = md5(password) # 彩虹表直接破
# 正確:bcrypt 或 Argon2(有 salt、有 cost factor)
hash = bcrypt.hashpw(password, bcrypt.gensalt(rounds=12))用途:密碼存儲、資料完整性驗證(Git commit hash、下載檔案 checksum)、blockchain。
Digital Signature(數位簽名)
私鑰簽名,公鑰驗證——證明「這個訊息確實來自私鑰持有者,且未被篡改」。
訊息 + 私鑰 → [Sign] → 簽名
訊息 + 簽名 + 公鑰 → [Verify] → 有效 / 無效
實際上簽的是訊息的 hash,不是訊息本身(訊息可能很大):
hash = SHA-256(訊息)
簽名 = RSA_encrypt(hash, 私鑰)
用途:
- TLS 憑證:CA 用私鑰簽發憑證,瀏覽器用 CA 的公鑰驗證
- JWT:server 用私鑰簽發 token,API 服務用公鑰驗 token
- Git commit signing:GPG 簽 commit,驗作者身份
- Docker image signing:Cosign / Notary 確認 image 來自可信來源
HMAC:對稱版的 Signing
Hash-based Message Authentication Code。用共享 secret key 對訊息做 hash——驗完整性 + 驗來源,但雙方都持有同一把 key。
HMAC = Hash(key + 訊息)
比非對稱 signing 快,但無法做到「non-repudiation」(雙方都有 key,都能偽造)。
用途:webhook signature(GitHub、Stripe 都用 HMAC-SHA256)、API request 簽名(AWS Signature V4)、JWT HS256 variant(單服務自用,不跨服務驗)。
選型速查
| 需求 | 用什麼 |
|---|---|
| 加密大量資料(靜態 / 傳輸中) | AES-256 |
| 安全分發 session key | RSA / ECDH |
| 存用戶密碼 | bcrypt / Argon2 |
| 驗資料完整性(非密碼) | SHA-256 |
| webhook / API 簽名(雙方共享 secret) | HMAC-SHA256 |
| JWT(跨服務驗身份) | RS256(非對稱)優於 HS256(對稱) |
| 憑證 / 身份驗證 | X.509 + RSA/ECC |
不要自己實作加密算法。 使用現有的加密庫(OpenSSL、libsodium、Python cryptography、Node.js crypto),即使你懂數學,密碼學實作有太多微小的 timing attack / padding oracle attack 陷阱。