密碼學系列 - 橢圓曲線 ECDSA - 簽名與驗籤

數字簽名的生成

假設Alice要給Bob發一個經過數字簽名的消息,他們首先需要定義一組共同接受的橢圓曲線加密用參數,簡單的,這組參數可表示爲 (CURVE, G, n)
其中,CURVE表示橢圓曲線點域和幾何方程;G是所有點倍積運算的基點;n是該橢圓曲線的可倍積階數(multiplicative order),作爲一個很大的質數,n的幾何意義在於,nG = 0,即點倍積nG的結果不存在,而對於小於n的任何一個正整數 m = [1,n-1],點倍積mG都可以得到一個合理的處於該橢圓曲線上的點。

其次,Alice要創建一對鑰,即一個私鑰和一個公鑰。私鑰來自於[1, n-1]範圍內一個隨機數:dA = rand(1, n-1)
公鑰如下,它來自私鑰和基點的橢圓曲線點倍積:QA = dA X G

Alice想要對消息m作數字簽名,有以下步驟:

  1. 計算 e = HASH(m),HASH是一個哈希加密函數,比如SHA-2,或SHA-3。
  2. 計算 z,來自e的二進制形式下最左邊(即最高位)L_n個bits,而L_n是上述橢圓曲線參數中的可倍積階數n的二進制長度。注意z 可能大於n,但長度絕對不會比 n 更長。
  3. 從 [1, n-1] 內,隨機選擇一個符合加密學隨機安全性的整數k
  4. 計算一個橢圓曲線上點:(x1, y1) = k X G
  5. 以下式計算 r 值, 如果r == 0, 則返回步驟3重新計算 r = x1 mod n
  6. 以下式計算 s 值,如果 s == 0,則返回步驟3重新計算
  7. 生成的數字簽名就是 (r, s)

在這裏插入圖片描述
Alice 用自己的私鑰和隨機數 k 簽名了哈希值 z。Bob 用 Alice 的公鑰來驗證簽名的正確性

特別需要注意的是步驟3中 k 的選擇,它不僅要滿足加密學的隨機安全性要求,要像私鑰一樣保護起來,更重要的是,在每次生成一個新的數字簽名時,這個 k 必須每次都要更新。否則,通過上述數字簽名過程中的算式相互換算,很容易從中破譯出私鑰!具體換算過程可見wiki_ECDSA。
ECDSA簽名可能泄漏私鑰的另一種方式是 {\ displaystyle k}ķ是由錯誤的隨機數發生器產生的。這樣的隨機數生成失敗導致Android比特幣錢包的用戶在2013年8月損失了資金

數字簽名的驗證

對於消息的接收方Bob來說,他除了收到數字簽名文件外,還會有一份公鑰。所以Bob的驗證分兩部分,首先驗證公鑰,然後驗證簽名文件(r, s)。

公鑰的驗證

  1. 公鑰QA的座標應是有效的,不會等於一個極限值空點O
  2. 通過公鑰QA的座標驗證它必須是處於該橢圓曲線上的點。
  3. 應有下式成立,即曲線的可倍積階數 n 與公鑰的點倍積不存在
    在這裏插入圖片描述

簽名文件的驗證

  1. 驗證 r 和 s 均是處於[1, n-1]範圍內的整型數;否則驗證失敗
  2. 計算 e = HASH(m),HASH()即簽名生成過程步驟1中使用的哈希函數。
  3. 計算 z,來自 e的最左邊L_n個bits
  4. 計算兩個參數 u1u2
    在這裏插入圖片描述
    在這裏插入圖片描述
  5. 計算(x1, y1),如果(x1, y1)不是一個橢圓曲線上的點,則驗證失敗:
    在這裏插入圖片描述
  6. 如果下面等式成立, 則簽名有效
    在這裏插入圖片描述

公鑰恢復

收到消息m 和愛麗絲的簽名r,s,在該消息上,Bob可以(可能)恢復Alice的公鑰:

  1. 驗證 rs 是整數 [1,n-1] 。如果不是,則簽名無效。
  2. 計算曲線點 R=(x1, y1) , x1是其中之一 r, r+n, r+2n等(提供的x1對於字段元素來說不是太大), y1是是滿足曲線方程式的值。
    請注意,可能有幾個滿足這些條件的曲線點,每個曲線點都不同 R 值將產生一個不同的已恢復密鑰。
  3. 計算 e = HASH(m),HASH()即簽名生成過程步驟1中使用的哈希函數。
  4. 計算 z,來自 e的最左邊L_n個bits
  5. 計算兩個參數 u1u2
    在這裏插入圖片描述
    在這裏插入圖片描述
  6. 計算曲線點
    在這裏插入圖片描述
  7. 如果QA匹配Alice的公鑰, 則簽名有效
  8. 如果嘗試了所有可能的R點且沒有匹配Alice的公鑰,則簽名無效。

請注意,無效的簽名或來自其他消息的簽名將導致恢復不正確的公鑰。如果事先知道簽名者的公鑰(或其哈希),則恢復算法只能用於檢查簽名的有效性。

公式推導請參考: wiki_ECDSA

公鏈簽名與驗籤算法

摘要生成 簽名算法 簽名數據格式 驗籤算法
BTC SHA256 ECDSA-secp256k1 BIP66之後採用DER編碼.
0x30 [total-length]
0x02 [R-length] [R]
0x02 [S-length] [S]
verify模式 OP_CHECKSIG
ECDSA_CheckSignature
(pubKeyStr,sigStr,
sha256(sha256(verifyThisStr)))
ETH SHA3-Keccack ECDSA-secp256k1 (R,S,V)
V是recid, 爲0或者1,
v := sig[0] - 27
recove模式
pub, err := crypto.Ecrecover(sighash[:], sig)
EOS SHA256 ECDSA-secp256k1|r1 (V,R,S)
V中帶了recid
v: 27 + 4 + recid,
從簽名中提取出recove id: V - 4 - 27
recove模式
recov = public_key_type( sig, digest )

公鏈 ECDSA 驗籤方式

用公鑰去verify的方式:

  1. BTC :

    ECDSA_CheckSignature(pubKeyStr,sigStr,sha256(sha256(verifyThisStr)))

    (參考資料: https://en.bitcoin.it/wiki/File:Bitcoin_OpCheckSig_InDetail.png )

  2. Hyperledger Fabric

    valid, err := id.msp.bccsp.Verify([id.pk](http://id.pk/), sig, digest, nil)

    (參考資料: https://blog.csdn.net/idsuf698987/article/details/81677133 )

recove出公鑰的方式:

  1. ETH
    pub, err := crypto.Ecrecover(sighash[:], sig) //摘自源碼
  2. EOS
    recov = public_key_type( sig, digest ) //摘自源碼

參考: Elliptic Curve Cryptography: ECDH and ECDSA

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章