ECDSA算法(深入浅出密码学笔记)

ECDSA标准中的步骤与DSA方案的步骤在概念上紧密相连,但ECDSA中的离散对数问题是在椭圆曲线群中构建起来的。因此,实际计算一个ECDSA签名所执行的算术运算与DSA中的完全不同。

ECDSA标准是针对素数域Zp\mathbb{Z}_pZp​和有限域GF(2m)GF(2^m)GF(2m)上的椭圆曲线定义的

密钥生成

  1. 使用椭圆曲线EEE,其中:模数为ppp;系数为aaa和bbb;生成素数阶qqq的循环群的点A
  2. 选择一个随机整数ddd,且0<d<q0<d<q0<d<q.
  3. 计算B=dAB=dAB=dA

密钥为:
kpub=(p,a,b,q,A,B)k_{pub}=(p,a,b,q,A,B)kpub​=(p,a,b,q,A,B)
kpr=(d)k_{pr}=(d)kpr​=(d)

注意:我们已经建立了一个离散对数问题,其中整数d为私钥,标量乘法的结果点B为公钥。与DSA一样,循环群的阶是q;而为了达到更高的安全等级,这个数的长度大小应该大于等于160位。

签名与验证

与DSA一样,ECDSAECDSAECDSA签名由一对整数(r,s)(r,s)(r,s)组成,其中每个值的位长度都与qqq相同,这也有助于实现十分简洁的签名。使用公钥和私钥计算消息xxx的签名的方式如下:

ECDSA签名生成

  1. 选择一个整数作为随机临时密钥kEk_EkE​,且0<kE<q0<k_E<q0<kE​<q。
  2. 计算R=kEAR=k_EAR=kE​A。
  3. 设置r=xRr=x_Rr=xR​。
  4. 设置s≡(h(x)+d⋅r)kE−1mod  qs\equiv(h(x)+d\cdot r)k_E^{-1} \mod qs≡(h(x)+d⋅r)kE−1​modq。

在步骤3中,点R的x坐标赋给变量r。在计算s时,必须使用函数h对消息x进行哈希。哈希函数的输出长度必须至少与q一样长。

ECDSA签名验证

  1. 计算辅助值w≡s−1mod  qw\equiv s^{-1} \mod qw≡s−1modq。
  2. 计算辅助值u1≡w⋅h(x)mod  qu_1\equiv w\cdot h(x) \mod qu1​≡w⋅h(x)modq。
  3. 计算辅助值u2≡w⋅rmod  qu_2\equiv w\cdot r \mod qu2​≡w⋅rmodq。
  4. 计算P=u1A+u2BP=u_1A+u_2BP=u1​A+u2​B。
  5. 验证verkpub(x,(r,s))ver_{k_{pub}}(x,(r,s))verkpub​​(x,(r,s))为:
    若xp≡rmod  qx_p\equiv r \mod qxp​≡rmodq则为有效签名;
    若xp≢rmod  qx_p \not\equiv r \mod qxp​​≡rmodq则为无效签名。

最后一步中的xpx_pxp​表示点P的x坐标。只有当xpx_pxp​与签名参数r模q相等时,验证者才会接受签名(r,s);否则,此签名将被看做时无效的。

证明就不放了,放个小例子吧

举例

首先,椭圆曲线为:E:y2≡x3+2x+2mod  17E:y^2\equiv x^3+2x+2 \mod 17E:y2≡x3+2x+2mod17

Bob选择p=17,a=2,b=2的曲线E和q=19的点A=(5,1)。选择d=7;计算B=dA=7⋅(5,1)=(0,6)Bob选择p=17,a=2,b=2的曲线E和q=19的点A=(5,1)。选择d=7;计算B=dA=7\cdot(5,1)=(0,6)Bob选择p=17,a=2,b=2的曲线E和q=19的点A=(5,1)。选择d=7;计算B=dA=7⋅(5,1)=(0,6)

Bob向Alice发送公钥(p,a,b,q,A,B)=(17,2,2,19,(5,1),(0,6))Bob向Alice发送公钥(p,a,b,q,A,B)=(17,2,2,19,(5,1),(0,6))Bob向Alice发送公钥(p,a,b,q,A,B)=(17,2,2,19,(5,1),(0,6))

签名:Bob计算消息h(x)=26的哈希值;选择临时密钥kE=10,R=10⋅(5,1)=(7,11),r=xR=7,s=(26+7⋅7)⋅2≡17mod  19签名:Bob计算消息h(x)=26的哈希值;选择临时密钥k_E=10,R=10\cdot (5,1)=(7,11),r=x_R=7,s=(26+7\cdot 7)\cdot 2\equiv 17 \mod 19签名:Bob计算消息h(x)=26的哈希值;选择临时密钥kE​=10,R=10⋅(5,1)=(7,11),r=xR​=7,s=(26+7⋅7)⋅2≡17mod19

发送签名:(x,(r,s))=(x,(7,17))发送签名:(x,(r,s))=(x,(7,17))发送签名:(x,(r,s))=(x,(7,17))

Alice方验证:Alice方验证:Alice方验证:
w=17−1≡9mod  19w=17^{-1}\equiv9 \mod 19w=17−1≡9mod19
u1=9⋅26=6mod  19u_1 =9\cdot 26=6 \mod 19u1​=9⋅26=6mod19
u2=9⋅7≡6mod  19u_2=9\cdot7\equiv6\mod 19u2​=9⋅7≡6mod19
P=6⋅(5,1)+6⋅(0,6)=(7,11)P=6\cdot(5,1)+6\cdot(0,6)=(7,11)P=6⋅(5,1)+6⋅(0,6)=(7,11)
xp≡rmod  19⇒有效的签名x_p\equiv r \mod 19\Rightarrow 有效的签名xp​≡rmod19⇒有效的签名

Python实现

需要引入模块ecdsa

import ecdsa

选取一个椭圆曲线,这里以NIST256p为例

gen = ecdsa.NIST256p.generator
order = gen.order()

ecdsa模块中有封装好了的函数可以赋值直接生成ecdsa公钥,私钥的对象

# 生成私钥d_A
d_A = random.randrange(1,order-1)
# 生成公私钥对象
public_key = ecdsa.ecdsa.Public_key(gen,gen * d_A)
private_key = ecdsa.ecdsa.Private_key(public_key,d_A)

数字签名

message = "message"
m = int(hashlib.sha1(message.encode("utf8")).hexdigest(),16)
# 临时密钥
k = random.randrange(1,order-1)
# 签名
signature = private_key.sign(m,k)
r = signature.r 
s = signature.s 

更多推荐