ECDSA标准中的步骤与DSA方案的步骤在概念上紧密相连,但ECDSA中的离散对数问题是在椭圆曲线群中构建起来的。因此,实际计算一个ECDSA签名所执行的算术运算与DSA中的完全不同。
ECDSA标准是针对素数域 Z p \mathbb{Z}_p Zp和有限域 G F ( 2 m ) GF(2^m) GF(2m)上的椭圆曲线定义的
密钥为:
k p u b = ( p , a , b , q , A , B ) k_{pub}=(p,a,b,q,A,B) kpub=(p,a,b,q,A,B)
k p r = ( d ) k_{pr}=(d) kpr=(d)
注意:我们已经建立了一个离散对数问题,其中整数d为私钥,标量乘法的结果点B为公钥。与DSA一样,循环群的阶是q;而为了达到更高的安全等级,这个数的长度大小应该大于等于160位。
与DSA一样, E C D S A ECDSA ECDSA签名由一对整数 ( r , s ) (r,s) (r,s)组成,其中每个值的位长度都与 q q q相同,这也有助于实现十分简洁的签名。使用公钥和私钥计算消息 x x x的签名的方式如下:
ECDSA签名生成
在步骤3中,点R的x坐标赋给变量r。在计算s时,必须使用函数h对消息x进行哈希。哈希函数的输出长度必须至少与q一样长。
ECDSA签名验证
最后一步中的 x p x_p xp表示点P的x坐标。只有当 x p x_p xp与签名参数r模q相等时,验证者才会接受签名(r,s);否则,此签名将被看做时无效的。
证明就不放了,放个小例子吧
首先,椭圆曲线为: E : y 2 ≡ x 3 + 2 x + 2 m o d 17 E:y^2\equiv x^3+2x+2 \mod 17 E:y2≡x3+2x+2mod17
B o b 选 择 p = 17 , a = 2 , b = 2 的 曲 线 E 和 q = 19 的 点 A = ( 5 , 1 ) 。 选 择 d = 7 ; 计 算 B = d A = 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)
B o b 向 A l i c e 发 送 公 钥 ( 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))
签 名 : B o b 计 算 消 息 h ( x ) = 26 的 哈 希 值 ; 选 择 临 时 密 钥 k E = 10 , R = 10 ⋅ ( 5 , 1 ) = ( 7 , 11 ) , r = x R = 7 , s = ( 26 + 7 ⋅ 7 ) ⋅ 2 ≡ 17 m o d 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))
A l i c e 方 验 证 : Alice方验证: Alice方验证:
w = 1 7 − 1 ≡ 9 m o d 19 w=17^{-1}\equiv9 \mod 19 w=17−1≡9mod19
u 1 = 9 ⋅ 26 = 6 m o d 19 u_1 =9\cdot 26=6 \mod 19 u1=9⋅26=6mod19
u 2 = 9 ⋅ 7 ≡ 6 m o d 19 u_2=9\cdot7\equiv6\mod 19 u2=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)
x p ≡ r m o d 19 ⇒ 有 效 的 签 名 x_p\equiv r \mod 19\Rightarrow 有效的签名 xp≡rmod19⇒有效的签名
需要引入模块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