前情
上篇《ECC Node.js》讲解椭圆曲线点的计算。本篇分析椭圆曲线签名算法。
代码
https://github.com/UMU618/secp256k1-tools
范例数据
已知,待签名数据为:
1 | const data = Buffer.from( |
运行 node ecc-sign.js
,信息摘要为:
1 | [ |
签名为:
1 | Uint8Array [ |
签名的字符串形式为:SIG_K1_Gg74ULRryVHxYZvMRLJgTrAZW6PZGC5SYfUiswtMJxBwfTTnGEnTejeWXopL2oSs8EZD7mqAC8mCps6VKq95Bgic9tGNHJ
分析
数值全部使用 16 进制表示。
- 范例使用的钥匙对
-
签名私钥:5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3
-
k =
d2653ff7cbb2d8ff129ac27ef5781ce68b2558c41a74af1f2ddca635cbeef07d
-
对应的公钥:EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
-
K = [
c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf
,eeceff7130fd352c698d2279967e2397f045479940bb4e7fb178fd9212fca8c0
]
-
信息先用 sha256 算法计算摘要,范例中值为 h =
cc1839b254811f68631e64d203261fa88af8fc83c40ecb9822986695b55eb694
-
签名数据一共 65 字节,第一个字节 [27] 是 recoveryParam,使用前要先减去 27,它的一个作用是区别 y 坐标值的奇偶性,后面是两个 256bit 数,分别记为 x、s,x 是随机私钥 r 在椭圆曲线上的点 rG 的 x 坐标值,s = (h + k * x) / r。
-
x =
24d3d62d14db559646aee583ad143d2581e85013a424f98438244ad222dd62a4
-
s =
4406ed2af0e3d42169efc80b3b0b94e255d46afa9b221965459f8a9d722c26ca
-
注意:elliptic 库把本文的 x 记为 r,为了和算法保持一致,UMU 没有采用 elliptic 的标识方式。
- 计算 rG = [
24d3d62d14db559646aee583ad143d2581e85013a424f98438244ad222dd62a4
,bc336258d8f1789ad949773ef4abfe6a6e56c9dd77754e18869c7ab2801a4ae2
]
1 | const BN = require('bn.js') |
- 计算 hG/s + x * K/s
-
u1 = h/s =
b774bb6040cced0596626026679594b2b5478e6a5a8ba25b3411ed5360ea6bfa
-
u2 = x/s =
5697dfd4caab3caa0ed315a97f99f1ad7bce1ce85e0be32c63847d1dd4be327a
-
result = u1 * G + u2 * K = [
24d3d62d14db559646aee583ad143d2581e85013a424f98438244ad222dd62a4
,bc336258d8f1789ad949773ef4abfe6a6e56c9dd77754e18869c7ab2801a4ae2
],与 rG 一致,签名验证通过。
1 | const BN = require('bn.js') |
数学原理
参考:椭圆曲线加密和签名算法
hG/s + xK/s = hG/s + x(kG)/s = (h + xk)G/s = r(h + xk)G / (h + kx) = rG