6.2 數位簽章的觀念#
概念說明#
數位簽章是非對稱世界裡的「手寫簽名」:簽署者用私鑰對訊息產生簽章 σ,任何人可用對應的公鑰驗證。與 MAC 的根本差異在金鑰不對稱——只有簽署者能簽,因此達成 MAC 做不到的不可否認性(non-repudiation)。
三個性質(對應 1.2 節四大目標):
- 完整性:訊息改一個 bit,簽章驗證即失敗。
- 真實性:簽章只能由私鑰持有者產生。
- 不可否認性:私鑰只有簽署者持有,簽章可交由任意第三方(含法庭)驗證。
演算法流程#
簽署:σ = Sign(d, H(M)) d = 私鑰,先對訊息雜湊再簽
驗證:Verify(Q, M, σ) ∈ {接受, 拒絕} Q = 公鑰
- 為何先雜湊:簽章演算法只能處理固定長度輸入;雜湊把任意長度訊息壓成安全摘要,同時加快簽驗速度。
- 三大體系:RSA 簽章(基於大數分解,7.2 節)、DSA/ECDSA(基於離散對數,7.1、7.3 節)、EdDSA(Ed25519,現代首選,速度與安全設計俱佳)。
Python 實作(使用業界標準)#
# pip install pynacl (Ed25519,TLS/SSH/區塊鏈廣泛使用)
from nacl.signing import SigningKey
import hashlib
sk = SigningKey.generate() # 私鑰
pk = sk.verify_key # 公鑰
msg = b"轉帳 100 元給 Alice"
sig = sk.sign(msg).signature
print(pk.verify(msg, sig)) # 驗證通過,返回訊息
try:
pk.verify(msg + b"0", sig) # 竄改後驗證
except Exception as e:
print("竄改被偵測:", type(e).__name__)
# 標準庫的 RSA 簽章見 7.2 節;此處再用 hashlib 展示「先雜湊」的摘要
print("簽章對象其實是摘要:", hashlib.sha256(msg).hexdigest()[:32])
安全性分析#
- 簽章 ≠ 加密反過來用:初學常見誤解「用私鑰加密=簽章」。教科書式 RSA 簽章若直接簽原始訊息(
σ = M^d mod n)存在多種結構攻擊(如乘法性攻擊可偽造複合訊息的簽章)。正確做法是使用填充方案:RSA-PSS(簽章)、RSA-OAEP(加密,7.2 節),絕不「裸簽」。 - 選擇前綴攻擊的教訓:MD5 憑證偽造(Flame 病毒,2012)證明「弱雜湊 + 簽章」的組合災難——攻擊者構造兩份同雜湊的文件,讓 CA 簽無害的那份,再把簽章移植到惡意的那份。
- 金鑰管理是真正的戰場:私鑰洩漏一切歸零。實務用 HSM、加密金鑰檔 + 強 passphrase、離線冷儲存(如加密貨幣冷錢包)。
- 簽章管不到的:公鑰的真實性——攻擊者可以把「自己的公鑰」冒充成你的。這個「公鑰配送問題」由下一節的 PKI 解決。
練習#
- 用 pynacl 簽署一份合約文字,隨後修改其中一個字元再驗證,記錄驗證失敗的例外訊息。
- 解釋 MAC 與簽章在「三方爭議」情境的差別:Alice 向 Bob 下單後反悔,若協定用的是 HMAC 而非簽章,仲裁者能否判斷是誰發的訊息?
- 查閱 RFC 8032(Ed25519),比較 Ed25519 與 ECDSA-P256 在「隨機數需求」上的差異——為什麼 ECDSA 的隨機數 k 重用會直接洩漏私鑰,而 Ed25519 是確定性的?