ECDSA 橢圓曲線數位簽章密碼學完整指南
深入分析 ECDSA 簽章的數學基礎、演算法實現與安全特性,包括 secp256k1 曲線參數、簽章生成與驗證過程、nonce 安全問題,以及在比特幣交易中的實際應用。
ECDSA 橢圓曲線數位簽章密碼學完整指南
橢圓曲線數位簽章演算法(ECDSA)是比特幣網路中最重要的密碼學基礎設施。用於驗證交易的所有權、確保消息的真實性,並實現比特幣的去中心化安全模型。本文深入分析 ECDSA 的數學基礎、演算法實現、安全特性以及在比特幣中的具體應用場景。
橢圓曲線密碼學數學基礎
橢圓曲線的代數定義
橢圓曲線在密碼學中的標準形式是 Weierstrass 方程:
y² = x³ + ax + b (mod p)
其中 a 和 b 是常數係數,p 是大質數。曲線上的點 (x, y) 必須滿足上述方程,且曲線不能有奇點(即導數不會同時為零),這要求 4a³ + 27b² ≠ 0 (mod p)。
secp256k1 曲線參數
比特幣採用的 secp256k1 曲線定義如下:
曲線方程:y² = x³ + 7 (mod p)
其中:
p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
= 2^256 - 2^32 - 977
基點 G:
Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
Gy = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
階 n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
輔助因子 h = 1
選擇 secp256k1 的原因是多方面的:首先,這條曲線在實現效率上具有優勢,因為 a = 0 簡化了曲線方程;其次,這條曲線經過了充分的密碼學分析,安全性得到了廣泛驗證;最後,NIST 曲線(比特幣未採用)存在爭議,secp256k1 提供了更透明的選擇。
有限域上的點運算
在有限域 Fp 上,橢圓曲線點的加法定義如下:
點加法公式(當 P ≠ Q):
λ = (y₂ - y₁) × (x₂ - x₁)⁻¹ (mod p)
x₃ = λ² - x₁ - x₂ (mod p)
y₃ = λ(x₁ - x₃) - y₁ (mod p)
倍點運算(當 P = Q):
λ = (3x₁² + a) × (2y₁)⁻¹ (mod p)
x₃ = λ² - 2x₁ (mod p)
y₃ = λ(x₁ - x₃) - y₁ (mod p)
標量乘法與循環群
橢圓曲線密碼學的安全性基於「橢圓曲線離散對數問題」(ECDLP):已知點 P 和 kP,求解 k 在計算上是不可行的。
比特幣使用 256 位元的私鑰 k,通過計算 Q = k × G 得到公鑰 Q。這就是比特幣地址生成的數學基礎。
ECDSA 簽章演算法詳解
簽章生成過程
ECDSA 簽章生成過程需要輸入待簽名消息的哈希值 h 和私鑰 d。輸出是簽名對 (r, s)。
演算法步驟:
輸入:消息哈希 h (256位元),私鑰 d
輸出:簽名 (r, s)
1. 計算 e = h mod n(將哈希值標準化為曲線階的範圍)
2. 選擇隨機nonce k ∈ [1, n-1]
3. 計算 (x₁, y₁) = k × G
如果 x₁ = 0,返回步驟2重新選擇k
4. 計算 r = x₁ mod n
如果 r = 0,返回步驟2重新選擇k
5. 計算 s = k⁻¹ × (e + r × d) mod n
如果 s = 0,返回步驟2重新選擇k
6. 返回簽名 (r, s)
簽章驗證過程
任何人都可以使用簽名、公鑰和消息哈希來驗證簽名的有效性。
演算法步驟:
輸入:簽名 (r, s),消息哈希 h,公鑰 Q
輸出:有效/無效
1. 驗證 r, s ∈ [1, n-1],否則返回無效
2. 計算 e = h mod n
3. 計算 u₁ = s⁻¹ × e mod n
計算 u₂ = s⁻¹ × r mod n
4. 計算 (x₁, y₁) = u₁ × G + u₂ × Q
5. 如果 (x₁, y₁) 是無窮遠點,返回無效
6. 計算 v = x₁ mod n
7. 如果 v = r,返回有效;否則返回無效
簽章格式與編碼
比特幣中的 ECDSA 簽名使用 DER(Distinguished Encoding Rules)編碼:
DER 簽名結構:
┌─────────────────────────────────────────────────────────┐
│ 0x30 [總長度] │
│ ├── 0x02 [r長度] [r值] │
│ └── 0x02 [s長度] [s值] │
└─────────────────────────────────────────────────────────┘
示例簽名(71-73 bytes):
30440220[32 bytes r]0220[32 bytes s]
比特幣還使用 sighash 類型位元組來指定簽名覆蓋的交易部分:
- SIGHASH_ALL (0x01):簽名覆蓋所有輸入和輸出
- SIGHASH_NONE (0x02):簽名不保護任何輸出
- SIGHASH_SINGLE (0x03):簽名只保護對應的輸出
- SIGHASH_ANYONECANPAY (0x80):與上述組合表示只保護當前輸入
簽章安全性分析
隨機數nonce的重要性
ECDSA 簽章中最關鍵的安全要素是隨機數 k(nonce)的選擇。如果同一私鑰的兩個簽名使用了相同的 k,攻擊者可以通過這兩個簽名直接計算出私鑰:
私鑰恢復攻擊:
已知:(r, s₁), (r, s₂), h₁, h₂
計算:
k = (h₁ - h₂) × (s₁ - s₂)⁻¹ mod n
d = s₁⁻¹ × (h₁ + r × k) mod n
比特幣史上因此類漏洞導致的私鑰洩露:
- 2010年:Sony PlayStation 3 私鑰洩露
- 2020年:多个 Bitcoin Core 开发者的签名泄露
確定性簽章(RFC 6979)
為了解決 nonce 選擇的安全問題,BIP-62 採用了 RFC 6979 確定的簽章生成方案:
確定性 k 的計算:
k = HMAC_SHA256(privkey || hash || counter)
重複直到 k ∈ [1, n-1]:
k = HMAC_SHA256(d || h || ctr)
ctr += 1
這種方法確保同一私鑰對同一消息總是產生相同的簽名,消除了隨機數產生器的依賴。
比特幣交易中的 ECDSA 應用
P2PKH 交易簽章
傳統的 Pay-to-Public-Key-Hash (P2PKH) 交易使用 ECDSA 簽名:
解鎖腳本 (scriptSig):
<signature> <pubKey>
鎖定腳本 (scriptPubKey):
OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
驗證過程:
1. OP_DUP 複製公鑰
2. OP_HASH160 計算公鑰哈希
3. 與輸出中的 pubKeyHash 比較
4. OP_EQUALVERIFY 驗證匹配
5. OP_CHECKSIG 使用 ECDSA 驗證簽名
隔離見證(SegWit)與 ECDSA
SegWit 升級改變了簽名的存儲位置,但仍然使用 ECDSA:
P2WPKH (Pay-to-Witness-Public-Key-Hash):
見證數據 (witness):
<signature> <pubKey>
鎖定腳本:
OP_0 <pubKeyHash>
驗證差異:
- 簽名不再包含在交易輸入中
- 見證數據單獨傳輸
- 解決了交易延展性問題
Schnorr 簽名與 Taproot
比特幣 2021 年 Taproot 升級引入了 Schnorr 簽名作為 ECDSA 的替代方案:
Schnorr 簽名生成:
輸入:私鑰 d,消息 h,隨機數 k
1. R = k × G
2. e = Hash(R || pubKey || h) mod n
3. s = k + e × d mod n
簽名:(R, s)
Schnorr 簽名的優勢包括:
- 線證:多性驗簽名交易可以將多個簽名聚合成單一簽名
- 不可否認性:無法將多簽名拆分為單獨簽名
- 安全性證明:具有可證明的安全性
ECDSA 與比特幣地址
地址生成流程
比特幣地址是公鑰的哈希表示,生成過程如下:
步驟 1:生成私鑰
私鑰 d ∈ [1, n-1](256位元隨機數)
步驟 2:計算公鑰
Q = d × G
公鑰未壓縮:04 || x || y (65 bytes)
公鑰壓縮:02/03 || x (33 bytes)
步驟 3:SHA256 哈希
hash1 = SHA256(公鑰)
步驟 4:RIPEMD-160 哈希
hash2 = RIPEMD160(hash1)
步驟 5:加入版本位元組
versioned_hash = 0x00 || hash2 (P2PKH)
versioned_hash = 0x05 || hash2 (P2SH)
步驟 6:校驗和
checksum = SHA256(SHA256(versioned_hash))[:4]
步驟 7:Base58Check 編碼
address = Base58Check(versioned_hash || checksum)
P2PKH 與 P2SH 地址
比特幣有兩種主要的地址格式:
P2PKH(Pay to Public Key Hash):
- 版本位元組:0x00
- 地址前綴:1
- 示例:1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2
- 腳本:OPDUP OPHASH160 <pubKeyHash> OPEQUALVERIFY OPCHECKSIG
P2SH(Pay to Script Hash):
- 版本位元組:0x05
- 地址前綴:3
- 示例:3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy
- 腳本:OPHASH160 <scriptHash> OPEQUAL
隔離見證地址(Bech32)
SegWit 引入了新的地址格式 Bech32:
P2WPKH(Native SegWit):
- hrp:bc
- 校驗和:Bech32
- 示例:bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq
- 腳本:OP_0 <pubKeyHash>
P2WSH(Pay to Witness Script Hash):
- 示例:bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3
- 腳本:OP_0 <scriptHash>
密鑰管理與 ECDSA 安全
私鑰安全存儲
比特幣私鑰的安全性完全依賴於用戶的保管。以下是最佳實踐:
硬體錢包:使用專用硬體設備存儲私鑰,永遠不暴露給連網設備。
紙錢包:將私鑰或助記詞以物理形式存儲,存放在安全位置。
多重簽名:使用 m-of-n 多重簽名方案,分散風險。
階層式確定性錢包(BIP-32)
現代比特幣錢包使用 BIP-32 確定性密鑰派生:
從 seed 生成主密鑰:
seed = HMAC-SHA512("Bitcoin seed", 密碼短語)
master_private_key = seed[:32]
master_chain_code = seed[32:]
從 master 生成子密鑰:
child_private_key = HMAC-SHA512(chain_code, parent_public_key || index)
child_public_key = child_private_key × G
這種設計允許從單一 seed 派生出大量地址,便於備份和管理。
量子計算威脅與 ECDSA 的未來
量子計算對 ECDSA 的威脅
量子計算機可以通過 Shor 演算法在多項式時間內解決橢圓曲線離散對數問題,這將使 ECDSA 完全失效。估計而言,破解比特幣的 256 位元曲線需要約 2000 邏輯量子位元的量子計算機。
後量子密碼學遷移
比特幣社群正在討論後量子遷移策略:
Lamport 簽名:基於哈希的簽名方案,安全性依賴哈希函數的抗碰撞性。
SPHINCS+:NIST 標準化的哈希簽名方案。
橢圓曲線同源加密(ECSIH):基於橢圓曲線同源問題的後量子方案。
混合簽名方案:結合傳統 ECDSA 和後量子簽名,實現逐步遷移。
結論
ECDSA 是比特幣安全的基石,通過橢圓曲線密碼學實現了去中心化的數位簽章。雖然面臨量子計算的潛在威脅,但比特幣社群已經開始規劃後量子遷移。理解 ECDSA 的數學基礎和實現細節對於比特幣開發者、安全研究人員和進階用戶至關重要。隨著 Schnorr 簽名和 Taproot 的引入,比特幣的簽名方案將繼續演進,為用戶提供更強大的安全性和隱私保護。
相關文章
- 比特幣密碼學基礎 — 深入理解比特幣核心密碼學技術:SHA-256、RIPEMD-160、secp256k1 橢圓曲線、ECDSA 與 Schnorr 簽章。
- Nakamoto 共識機制 — 深入分析比特幣的革命性共識機制:工作量證明、最長鏈原則、激勵相容性與安全性分析。
- Taproot 全面解析 — 比特幣最新的腳本升級:MAST、BIP-340/341/342。
- 比特幣錢包內部運作機制完整指南 — 深入解析比特幣錢包的內部運作原理,包括 HD 錢包 BIP-32/39/44 標準、私鑰管理、地址生成、交易建構與簽章流程,以及錢包備份與安全策略。
- OP_CHECKTEMPLATEVERIFY 深度技術分析 — 深入分析 BIP 119 提出的 CTV 技術原理、應用場景、優勢與風險,以及當前發展狀態。
延伸閱讀與來源
這篇文章對您有幫助嗎?
請告訴我們如何改進:
評論
發表評論
注意:由於這是靜態網站,您的評論將儲存在本地瀏覽器中,不會公開顯示。
目前尚無評論,成為第一個發表評論的人吧!