Standards Track Final
BIP-66: 嚴格 DER 簽章
強制要求比特幣交易使用嚴格的 DER 編碼簽章格式,修復潛在安全漏洞。
Pieter Wuille 2015年1月10日
BIP 編號
66
類型
Standards Track
狀態
Final
創建日期
2015-01-10
摘要
BIP-66 引入了一個新的共識規則,要求所有 ECDSA 簽章必須嚴格遵守 DER(Distinguished Encoding Rules)編碼格式。 這修復了 OpenSSL 實現中的潛在安全漏洞,並確保所有節點對簽章驗證有一致的行為。
背景
OpenSSL 的問題
早期比特幣使用 OpenSSL 庫來驗證 ECDSA 簽章。OpenSSL 對 DER 編碼的解析較為寬鬆, 接受多種非標準格式:
風險
- • 不同版本的 OpenSSL 可能對同一簽章有不同判斷
- • 可能導致網路分裂(consensus failure)
- • 攻擊者可利用此不一致性製造混亂
DER 編碼規則
簽章結構
ECDSA 簽章 DER 格式: ┌──────────────────────────────────────────────────────┐ │ 0x30 [total-len] 0x02 [r-len] [r] 0x02 [s-len] [s] │ └──────────────────────────────────────────────────────┘ 各欄位說明: • 0x30 : SEQUENCE 標記 • total-len: 後續所有資料的長度 • 0x02 : INTEGER 標記(r 值) • r-len : r 值的長度 • r : r 值(big-endian,無前導零,除非需要避免負數) • 0x02 : INTEGER 標記(s 值) • s-len : s 值的長度 • s : s 值(同上規則)
嚴格規則
BIP-66 要求簽章必須滿足以下所有條件:
1. 正確的標記 — 必須以 0x30 開頭,r 和 s 必須以 0x02 開頭
2. 正確的長度 — 長度欄位必須準確反映實際資料長度
3. 最小編碼 — r 和 s 不能有多餘的前導零(除非最高位是 1)
4. 正數表示 — 如果 r 或 s 的最高位是 1,必須加 0x00 前綴避免被解讀為負數
5. 非零值 — r 和 s 不能是零
合法簽章範例
合法簽章(71 bytes):
30 44 // SEQUENCE, 長度 68
02 20 // INTEGER, 長度 32
7a8e...(32 bytes r)
02 20 // INTEGER, 長度 32
3b1c...(32 bytes s)
01 // SIGHASH_ALL
不合法範例:
• 30 45 02 21 00 7a8e... — r 有不必要的 0x00 前綴
• 30 43 02 1f 7a8e... — r 少了一個位元組(無效長度)
• 30 44 02 20 00 00... — r 以多個 0x00 開頭 部署方式
BIP-66 使用區塊版本號進行軟分叉部署:
| 參數 | 值 |
|---|---|
| 區塊版本 | 3(或更高) |
| 啟用閾值 | 最近 1000 區塊中 750 個是 v3+ |
| 啟用區塊 | 363,725(2015-07-04) |
| 強制區塊 | 363,724 後的所有區塊 |
影響
好處
- • 消除 OpenSSL 相關的共識風險
- • 所有節點行為一致
- • 為移除 OpenSSL 依賴鋪路
- • 減少交易延展性
注意事項
- • 舊版錢包可能生成非嚴格簽章
- • 需要更新簽章生成代碼
- • 不影響已確認的歷史交易
後續發展
BIP-66 是減少比特幣對 OpenSSL 依賴的重要一步。後續發展包括:
- • libsecp256k1:Bitcoin Core 現在使用自己的 ECDSA 庫
- • BIP-146:進一步限制簽章格式(低 S 值)
- • Schnorr 簽章:BIP-340 引入更簡潔的簽章格式
總結
BIP-66 是一個重要的安全性改進,確保所有節點對簽章驗證有相同的行為。 雖然對終端使用者透明,但它消除了一類潛在的共識失敗風險, 是比特幣協議穩健性的重要保障。
延伸閱讀
延伸閱讀: 查看 GitHub 上的完整 BIP-66 文件
已複製連結