密碼學在解決什麼問題
1. 為什麼要關心這個問題?
一個開發者用 AES 加密使用者密碼。另一個用 MD5 簽署 API 請求。第三個用 RSA 加密幾個 GB 的影片檔案。
三個都是錯的。
不是因為這些演算法有問題,而是因為他們用錯了工具。就像用錘子鋸木頭——錘子沒問題,你只是用錯了方式。
密碼學不是一個單一的東西。它是一個工具箱,每個工具解決特定的問題。在需要雜湊的地方用加密,或者在需要簽章的地方用雜湊,你的「安全」系統就變成了一個隱患。
2. 定義
密碼學 是透過數學技術保護資訊的科學。它為恰好四個基本安全問題提供解決方案:
- 機密性: 保守秘密
- 完整性: 偵測未經授權的修改
- 認證: 驗證身分
- 不可否認性: 防止否認行為
每個問題需要不同的工具。沒有單一演算法能解決全部四個問題。
3. 密碼學安全的四大支柱
機密性:「只有預期的接收者能讀取」
問題: 你想發送一條只有 Alice 能讀取的訊息,即使 Eve 截獲了它。
解決方案: 加密
- 對稱加密(AES、ChaCha20)
- 非對稱加密(RSA、ECIES)
它不解決什麼:
- 訊息是否被竄改
- 發送者是否是他們聲稱的那個人
- 發送者是否能否認發送過它
# 機密性:AES 加密
ciphertext = aes_encrypt(plaintext, key)
# Eve 截獲了密文但無法讀取
# 但是:Eve 可以在不被偵測的情況下修改密文!完整性:「這條訊息沒有被竄改」
問題: 你收到一條訊息,需要驗證它在傳輸過程中沒有被修改。
解決方案: 雜湊函式和 MAC
- 雜湊函式(SHA-256、SHA-3)
- 訊息認證碼(HMAC)
它不解決什麼:
- 保持訊息內容的機密性
- 證明是誰發送的訊息(對於沒有金鑰的雜湊)
# 完整性:雜湊驗證
original_hash = sha256(message)
# 稍後...
if sha256(received_message) != original_hash:
raise TamperedMessageError()
# 但是:任何人都可以計算雜湊——這不能證明是誰發送的!認證:「這條訊息來自它聲稱的發送者」
問題: 你收到一條聲稱來自 Alice 的訊息。你如何驗證它真的來自她?
解決方案: 數位簽章和 MAC
- 數位簽章(RSA-PSS、ECDSA、EdDSA)
- HMAC(使用共享金鑰)
區別:
- HMAC: 雙方共享一個金鑰。你知道它來自知道金鑰的人。
- 數位簽章: 只有私鑰持有者能簽章。你可以用公鑰驗證。
# 認證:數位簽章
signature = sign(message, alice_private_key)
# 任何人都可以驗證
is_authentic = verify(message, signature, alice_public_key)不可否認性:「發送者不能否認發送過這個」
問題: Alice 發給你一份合約。後來,她聲稱她從未發送過。你如何證明她發送過?
解決方案: 數位簽章(僅限非對稱!)
為什麼 HMAC 不行: 使用 HMAC 時,雙方共享同一個金鑰。如果 Alice 有金鑰,你也有金鑰——你們任何一方都可能建立了這條訊息。Alice 可以聲稱是你寫的。
為什麼數位簽章可以: 只有 Alice 的私鑰能建立有效的簽章。如果簽章用她的公鑰驗證通過,它一定來自她的私鑰。她無法否認。
# 不可否認性:只有非對稱簽章提供這個
signature = sign(contract, alice_private_key)
# Alice 不能聲稱她沒簽——只有她的私鑰能建立這個簽章4. 演算法-問題矩陣
| 問題 | 雜湊 | HMAC | 對稱加密 | 非對稱加密 | 數位簽章 |
|---|---|---|---|---|---|
| 機密性 | ❌ | ❌ | ✅ | ✅ | ❌ |
| 完整性 | ✅* | ✅ | ❌ | ❌ | ✅ |
| 認證 | ❌ | ✅ | ❌ | ❌ | ✅ |
| 不可否認性 | ❌ | ❌ | ❌ | ❌ | ✅ |
*雜湊僅在你有原始雜湊的可信副本時提供完整性驗證。
5. 誤用導致的常見災難
災難 1:加密密碼
# 錯誤:用加密儲存密碼
encrypted_password = aes_encrypt(password, key)
database.store(encrypted_password)
# 問題:如果金鑰被竊,所有密碼立即暴露
# 另外:你為什麼需要解密密碼?正確做法: 用 bcrypt/argon2 雜湊密碼。你永遠不需要恢復原始密碼——你只需要驗證。
災難 2:用雜湊實現機密性
# 錯誤:用雜湊當「加密」
"secure_data" = sha256(sensitive_data)
# 問題:雜湊是單向的,但是確定性的
# 相同輸入 = 相同輸出 = 可能進行模式分析
# 而且你永遠無法恢復原始資料正確做法: 如果需要恢復資料,使用真正的加密。
災難 3:用 HMAC 實現不可否認性
# 錯誤:用 HMAC 簽合約
mac = hmac(contract, shared_secret)
# 問題:雙方都有金鑰
# Alice:「我沒簽這個——Bob 也有同樣的金鑰,他可能寫的」正確做法: 對任何需要不可否認性的東西使用數位簽章。
災難 4:用 RSA 加密大資料
# 錯誤:用 RSA 加密大檔案
encrypted_video = rsa_encrypt(video_file, public_key) # 極其慢!
# 問題:RSA 比 AES 慢約 1000 倍
# 另外:RSA 有訊息大小限制正確做法: 使用混合加密——用 AES 加密資料,用 RSA 加密 AES 金鑰。
6. 真實系統如何組合工具
現實世界的安全需要多個密碼學原語協同工作。
HTTPS/TLS 交握
┌─────────────────────────────────────────────────────────┐
│ 1. 金鑰交換(機密性 + 認證) │
│ - ECDHE 實現前向保密 │
│ - 伺服器憑證(RSA/ECDSA 簽章) │
├─────────────────────────────────────────────────────────┤
│ 2. 資料傳輸(機密性 + 完整性) │
│ - AES-GCM 加密 │
│ - 內建認證標籤(完整性) │
└─────────────────────────────────────────────────────────┘JWT(JSON Web Token)
┌─────────────────────────────────────────────────────────┐
│ Header.Payload.Signature │
├─────────────────────────────────────────────────────────┤
│ 簽章提供: │
│ - 完整性:權杖不能被修改 │
│ - 認證:伺服器可以驗證發行者 │
├─────────────────────────────────────────────────────────┤
│ 簽章不提供: │
│ - 機密性:Payload 是 Base64,不是加密的! │
└─────────────────────────────────────────────────────────┘7. 決策框架
選擇密碼學工具時,問:
你需要恢復原始資料嗎?
├─ 否 → 考慮雜湊
│ └─ 是密碼嗎?→ 使用 bcrypt/argon2
│ └─ 是用於完整性驗證?→ 使用 SHA-256/SHA-3
│
├─ 是 → 你需要加密
│ └─ 誰持有金鑰?
│ ├─ 同一方加密/解密 → 對稱(AES)
│ └─ 不同方 → 非對稱或混合
│
你需要證明是誰發送的嗎?
├─ 可以接受共享金鑰?→ HMAC
└─ 需要不可否認性?→ 數位簽章8. 本章小結
三點要記住:
一個演算法,一個問題。 加密提供機密性。雜湊提供完整性。簽章提供認證和不可否認性。不要混淆它們。
不可否認性需要非對稱密碼學。 如果雙方共享金鑰,都無法證明對方發送了訊息。只有數位簽章提供不可否認性。
真實系統組合多個原語。 HTTPS 同時使用金鑰交換、加密和認證。理解哪個工具做什麼,有助於你理解協定為什麼這樣設計。
9. 下一步
現在我們理解了密碼學解決的四個問題。但我們多次提到「對稱」和「非對稱」加密卻沒有解釋區別。
在下一篇文章中,我們將探討:為什麼我們需要兩種完全不同類型的加密?它們的權衡是什麼,真實系統如何組合使用它們?
