ECDSA的最简理解

椭圆曲线

y^2 = (x^3 + a * x + b) mod p

上述的曲线是在整数,一定bit数量(假设是160bit)内可以表达的,p是 160bits内可以表示的大整数。

为什么是这种曲线定义呢,我个人觉得有3个原因:

  1. 在这个曲线上加法是可定义的。
  2. 在这个曲线上的加法求解很简单。
  3. 在这个曲线上可以证明 对数运算是极复杂问题。

标量加法/乘法定义

在椭圆曲线上随意取两个点 A,B,连接A,B两个点的直线与曲线的新的交点称为C,C关于X对称的-C点表示为 A+B。

乘法可以用加法表示,但是算法复杂堵是 log(n)。

其实为什么选择上述的椭圆曲线实际上是由这个加法规则选出来的,总是要求解这个新的交点更加简单。

Trap door fuction(陷门函数)

R=k*P的性质,已知R与P的值,无法推出k的值, 而知道k值于P值是很容易计算R值(log(n))。这是ECDSA签名算法的理论基础。

如何设计签名算法

如何利用这个门限函数来做一个签名算法呢?

一个顺理成章的想法是: 给验证人一个 R和P,那只有签名人才能提供K,那K是不是可以作为一个签名指纹呢?

ok,咱先生成一个公私钥对,Qa = dA * G , Qa 就是公钥,dA是一个随机数,就当是一个私钥吧,当然这个椭圆曲线的 a, b, p, G 值都是要公开的。这个G 就是椭圆曲线上随机挑选的一个节点,我们叫原点,也是要公开的。

每次对一个数据做签名,都随机生成一个随机数 K 吧,P = K * G。咱们把 P的x轴坐标R作为签名的一部分。另一部分签名数据叫 S
显然这个S既要和 dA相关,也要和被签名的信息z相关。我们就假定:

S = Sig(dA, G, z, R, K), 那这个函数就是签名函数。

而验证函数应该只有 S,R,而不会有K,dA

P = h(S, G, z, R), h 就是签名函数。

密码学专家想到了一个实现:
S = k^-1 (z + dA * R) mod p

k^-1 表示的是关于p的模逆元。( k^-1 * k mod p = 1)。
可以推倒初验证函数:
==> k = S^-1 (z + dA * R) mod p
==> k*G = S^-1 (z + dA * R) *G
==> P = S^-1*z*G + S^-1*dA*R*G
==> P = S^-1*z*G + S^-1*R*Qa

对于验证者来说,需要计算: S^-1*z*G + S^-1*R*Qa 的x坐标是否就是 R

实现

go的椭圆曲线 a 为固定的-3, 而b可以自由的选择,而p224, p256曲线的其实指的是 曲线的bit位数是224和256。

算法实现着为了更加快速地执行曲线上的加法和乘法,对笛卡尔坐标做了投射成(x,y,z)的雅各布坐标,投射关系:

x'=x * (Z^-2) 
y'=y * (Z^-3) 

可以加速在雅各布坐标系上的运算,在需要最终结果的时候再投射回笛卡尔坐标系。
一个曲线的表示:

type CurveParams struct {
    P       *big.Int // the order of the underlying field
    N       *big.Int // the order of the base point
    B       *big.Int // the constant of the curve equation
    Gx, Gy  *big.Int // (x,y) of the base point
    BitSize int      // the size of the underlying field
    Name    string   // the canonical name of the curve
}

公私钥对的表示:

// PublicKey represents an ECDSA public key.
type PublicKey struct {
    elliptic.Curve
    X, Y *big.Int
}

// PrivateKey represents an ECDSA private key.
type PrivateKey struct {
    PublicKey
    D *big.Int
}

可以看出曲线,公钥,私钥拥有的信息越来越全。
公钥是 曲线信息+ dA*G的信息。
私钥是 公钥信息 + dA信息。

secp256k1

美国国安局发布的曲线其实是 secp256k1, 对于其参数其实没有很好的解释,大家猜测是国安局找到了这是一条弱化的椭圆曲线,因此BTC在设计之初也没有采用这个曲线,而是用了Koblitz Curve, b是7,a是0,btcsuit的package中,对KoblitzCurve是golang的 curvparam 的一层封装(主要是为了加速),但是有更多的参数, 是因为a和b等参数都是预先设定的,增加更多的参数来加速计算。至于公私方法和golang基本一样。

ED25519

Ed25519 从某种意义上来说也属于椭圆曲线密码学,不同的是它采用扭曲爱德华兹曲线作为椭圆曲线,同时采用的签名机制也不同于 ECDSA 算法。EdDSA 的重要实现 ED25519 是 Daniel J. Bernstein 等人设计的 EdDSA 算法,采用的曲线参数完全公开,并说明了参数选取的意义,保证曲线中并未内置后门。

曲线:
y^2 = (x^3 + x^2 + {一个很大的随机数}x ) mod p

他生成公私钥的流程有一些区别,seed作为私钥,seed计算出的hash值去和G相乘得到公钥,为了防止多次计算,把这部分公钥扩展到私钥的后面作为一个完整的私钥。计算签名的时候,普通ecdsa会生成一个随机数K,而ec25519为了避免伪随机数被猜测到,因此是私钥和msg的hash值作为这个随机数。

你可能感兴趣的:(ECDSA的最简理解)