密码学系列 - 椭圆曲线 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

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