跳到主要内容

椭圆曲线加密算法

· 阅读需 15 分钟

椭圆曲线定义

椭圆曲线加密算法(Elliptic curve cryptography)简称 ECC,是一种非对称加密算法。方程式为

y2=x3+ax+b4a3+27b20y^2 = x^3 + ax +b,4a^3 + 27b^2 \neq 0

如下是不同的 aabb 取值绘制的椭圆曲线图

从图中可以看出,椭圆曲线是关于 x 轴对称的曲线。

需要注意的是 aabb 须满足条件 4a3+27b204a^3 + 27b^2 \neq 0,这个条件确保了曲线的光滑,即曲线中不存在尖点,自相交点和孤立点,从而保证曲线上的点都有切线。

椭圆曲线的四则运算

椭圆曲线的四则运算不同于代数中的四则运算。其有自己的运算法则。

加法

已知椭圆曲线上的点PP和点QQ,过这两点做直线,与椭圆曲线相交于第三个点RR,做点RR与 x 轴的对称点RR'。这个RR'点就时PPQQ相加的结果,P+Q=RP + Q = R’

P=QP=Q时,相当于过点 P 做曲线的切线,相交于点RRRR 关于 X 轴的对称点 RR' 就是相加得到的点。 P+P=2P=RP + P = 2P = R'

Q=PQ=-P时,即QQ点是PP点在椭圆曲线上关于 X 轴的对称点,此时过这两点做直线。没有相交的第三个点。假设P+Q=OP+Q = O,则P+Q=P+(P)=OP + Q = P + (-P) = O

OO是一个无穷远点,也叫加法的单位元。曲线上任意点与单位元相加都等于其自身。 P+O=PP + O = P

还有一种情况是 PPQQ 连接的直线没有第三个交点的情况

这种情况就是一条直线穿过 P 和 Q 与曲线相切,P 是切点,此时P+Q=PP+Q = -P, 同样如果 Q 是切点,则P+Q=QP+Q=-Q

减法

PQP-Q 可以看成P+(Q)P + (-Q)

首先计算 QQ 关于 X 轴的对称点Q-Q,连接PPQ-Q相交于RR, RR关于 X 轴的对称点RR'就是计算结果。

乘法

已知椭圆曲线上的点 P 和数值 n,求 nP,可以看成是 n 个 P 相加 例如 P+P+PP + P+ P

首先计算 P+PP + P,过PP点做切线与曲线相交于R1R_1R1R_1 关于 X 的对称点2P2P就是 P+PP+P的结果,连接2P2P点和pp点相交于R2R_2点,R2R_2关于 X 轴的对称点3P3P就是最终的计算结果

有限域椭圆曲线

上面所说的是在实数域上椭圆曲线,实数是具有连续性的,这种连续性并不适用于安全加密。因此需要把椭圆曲线变成离散的点,也就是定义在有限域上。

有限域是指有限个元素的集合,记做 GF(p)GF{(p)}𝔽p𝔽_p, pp是素数,有{0,1,2,3...,p1}\{0,1,2,3...,p-1\}共 p 个元素。如𝔽7={0,1,2,3,4,5,6}𝔽_7=\{0, 1, 2, 3, 4, 5, 6\}

在这个有限域中,椭圆曲线的运算都是基于取模运算的,也就是取余数

  • 加法:a+b=c mod pa + b = c \ mod \ p
  • 减法:ab=a+(b) mod pa-b = a + (-b) \ mod\ p
  • 乘法:ab=c mod pa * b = c \ mod \ p
  • 除法:a÷b=a×b1=c mod pa \div b = a \times b ^ {-1}=c \ mod\ p

在有限域𝔽p𝔽_p上的椭圆曲线上满足:

  • y2=x3+ax+by^2 = x^3 + ax + b 上的所有点的 xxyy 坐标值是𝔽p𝔽_p中的两个整数,因此有限域椭圆曲线图是一定数量的点形成的图
  • aabb 是满足4a3+27b204a^3 + 27b^2 \neq 0且在𝔽p𝔽_p中的两个整数

记作Ep(a,b)E_p(a, b), 如:E5(1,1):y2=x3+x+1 mod 5E_{5}(1, 1): y^2 = x^3 +x + 1\ mod\ 5

即对于某个xxyy 的组合等式两边的结果对 5 取余是相等的,则认为该点是有效的

由于xxyy 的取值是在有限域中整数,因此对于上式中有多个可组合的点:

  • x=0,y=1x=0, y=1, 左右两边对 5 取余结果都为 1,该点有效
  • x=0,y=2x = 0, y = 2, 左边对 5 取余结果为 4,右边对 5 取余结果为 1,两边不等,该点无效
  • x=0,y=4x = 0, y = 4, 左右两边对 5 取余结果都为 1,该点有效

如此遍历下去,便能确定最终的有效点为(0,1) (0,4) (2,1) (2,4), (3,1) (3,4) (4,2) (4,3)(0, 1)\ (0,4)\ (2, 1)\ (2, 4), \ (3, 1)\ (3, 4)\ (4,2)\ (4,3)

有限域椭圆曲线加法

假设有限域椭圆曲线E127(1,3):y2=x3x+3 mod 127E_{127}(-1, 3): y^2=x^3 -x +3 \ mod \ 127

P=(16,20)P=(16, 20), 点Q=(41,120)Q =(41,120)P+QP+Q 的坐标点R(xy)R'(x', y')

首先计算连接PPQQ 直线的斜率k=yPyQxPxQmod p=201201641mod 127=4mod 127=4k = \frac {y_P - y_Q}{x_P - x_Q} \mod \ p= \frac {20-120}{16-41} \mod \ 127=4 \mod\ 127 = 4

接着计算直线和曲线相交的第三个点的坐标R(x,y)R(x, y)

xR=k2xPxQ mod p=161641 mod 127=41 mod 127=86x_R = k^2 - x_P - x_Q \ mod\ p = 16-16-41 \ mod\ 127 = -41 \ mod\ 127 = 86

yR=[yP+k(xRxP)] mod p=[20+4(8616)] mod 127=300 mod 127=46y_R=[y_P + k(x_R-x_P)] \ mod\ p = [20 + 4(86 - 16)]\ mod\ 127 = 300\ mod\ 127 = 46

RR'RR关于xx轴的对称点,所以

xR=xR=86yR=yR mod p=46mod 127=81x_{R'} = x_R = 86, y_{R'}=-y_R \ mod\ p = -46 \mod \ 127 = 81

所以 P+Q=(86,81)P+Q = (86, 81)

如果P=QP=Q, 则斜率k=3xP2+a2yP mod pk = \frac {3x_P^2 + a}{2y_P} \ mod\ p

有限域椭圆曲线乘法

在实数域中的乘法定义为:nP=P+P++PnP = P + P +\cdots + P, 对PP逐次累加计算。在有限域中同样可以这样计算

但在有限域中椭圆曲线中的乘法会存在一个循环,例如存在有限域椭圆曲线E97(2,3):y2=x3+2x+3 mod 97E_{97}(2, 3): y^2=x^3+2x+3 \ mod\ 97 和点P(3,6)P(3, 6)

  • 0P=00P = 0
  • 1P=(3,6)1P = (3, 6)
  • 2P=P+P=(80,10)2P = P + P = (80, 10)
  • 3P=2P+P=(80,87)3P=2P+P=(80, 87)
  • 4P=3P+P(3,91)4P=3P+P(3, 91)
  • 5P=4P+P=05P = 4P+P=0
  • 6P=5P+P=(3,6)6P=5P+P=(3, 6)
  • 7P=6P+P=(80,10)7P =6P+P =(80, 10)
  • \cdots

可视化查看网页

当点击点P(3,6)P(3, 6) 时,可以看到循环次数为 5,以及循环计算得到的点集(称循环子群)。该点集的数量就叫做阶。即 5 是点P(3,6)P(3,6)的阶。

PP的阶和椭圆曲线是有联系的,拉格朗日定理告诉我们,子群的阶是父群的阶的因子。换句话说,如果一个椭圆曲线包含 NN 个点,它的一个子群包含 nn 个点,那么 nnNN 的因子

因此计算点PP的阶就可以遵循下面的步骤:

  • 计算椭圆曲线的阶NN (上面定义了阶是点集的数量,因此NN 就是有限域上椭圆曲线的有效点的数量)
  • 找出NN的所有因子
  • 对每个因子计算nPnP
  • 找到最小的且满足 nP=0nP=0nn, nn 就是子群的阶

例如对于椭圆曲线E37(1,3):y2=x3x+3 mod 37E_{37}(-1, 3): y^2=x^3-x+3 \ mod\ 37

共有 42 个点,因此 N=42N = 42。42 的因子有 1,2,3,6,7,14,21,421,2,3,6,7,14,21,42 依次与点P(2,3)P(2,3) 相乘

1P0,2P0,,7P=01P\neq 0, 2P\neq0,\cdots,7P=0, 因此PP的阶是 7。

椭圆曲线加密算法

ECC

在椭圆曲线加密算法中,给定椭圆曲线EE, 基点GG,可以很容易算出GG的阶nn,然后在{1,,n1}\{1,\cdots,n-1\} 中随机选择一个整数kk 作为私钥,公钥H=kGH=kG

因此知道 kkGG 可以很容易算出公钥 HH , 但如果知道HHGG,要算出私钥kk 就很难了。这里涉及到了离散对数的问题

ECDH

ECDH 是椭圆曲线的笛福赫尔曼算法的变种,它其实不单单是一种加密算法,而是一种密钥协商协议, 也就是说 ECDH 定义了密钥怎么样在通信双方之间生成和交换。

假设现在有 A 和 B 想要通信,在ECDH 通信是下面这样的:

  • A 选择了一条有限域上椭圆曲线Ep(a,b)E_p(a,b) 并选择了一个基点GG, 生成了自己的公钥和私钥。之后将自己的椭圆曲线Ep(a,b)E_p(a,b)、基点GG 和公钥传给 B。B 根据这些信息生成自己的公钥和私钥
    • A 的私钥记作kAk_A,公钥HA=kAGH_A = k_AG
    • B 的私钥记作kBk_B,公钥HB=kBGH_B = k_BG
  • A 和 B 交换各自的公钥
  • A 计算共享秘钥S=kAHBS=k_AH_B(使用自身的私钥和 B 的公钥), B 计算共享秘钥S=kBHAS=k_BH_A(使用自身的私钥和 A 的公钥), A 和 B 计算得到的SS 是相同的,因为S=kAHB=kA(kBG)=kB(kAG)=kBHAS=k_AH_B = k_A(k_BG) = k_B(k_AG)=k_BH_A
  • 使用共享秘钥来加密数据进行通信。

ECDSA

椭圆曲线签名算法(ECDSA)就是使用 ECC 对 DSA 数字签名算法的模拟,最终签名可得到两个值 r 和 s。验证签名只需要求解一个值,判断值是否与 r 相同,如果相同,则说明是有效签名。

已知椭圆曲线Ep(a,b)E_p(a, b) 、基点GGGG的阶数nn,要发送的消息的哈希h=hash(message)h=hash(message),经过计算后 h 会是一个整数

A 首先生成自己的公钥和私钥,即从{1,,n1}\{1,\cdots,n-1\}随机选择一个数kAk_A作为私钥,公钥 HA=kAGH_A=k_AG

A 生成签名过程如下

  • {1,,n1}\{1,\cdots,n-1\} 中选择一个随机数kk
  • 计算 P(x,y)=kGP(x, y)=kG
  • 计算r=xP mod nr = x_P\ mod\ nxPx_PPP点的xx坐标),若r=0r=0, 则重新选择一个kk 并重新计算
  • 计算s=k1(h+rkA) mod ns=k^{-1} (h+rk_A) \ mod\ nkAk_A是 A 的私钥,k1k^{-1}kk的乘法逆元, h 是要发送消息的哈希),若s=0s=0 ,则重新选择一个kk并重新计算

为了验证签名,我们需要将 A 的公钥 HAH_A ,消息哈希hh,签名信息(r,s)(r,s),发送给 B

B 验证签名过程如下:

  • 计算u1=s1h mod nu_1 = s^{-1}h \ mod \ n
  • 计算u2=s1r mod nu_2 = s^{-1}r \ mod \ n
  • 计算P=u1G+u2HAP = u_1G + u_2H_A, 当 r=xP mod nr = x_P \ mod \ nx_P为$$Pxx坐标),则验证成功

P=u1G+u2HA=u1G+u2kAG=(u1+u2kA)G=(s1h+s1rkA)G=(h+rkA)s1GP = u_1G + u_2H_A = u_1G + u_2k_AG = (u_1 + u_2k_A)G = (s^{-1}h + s^{-1}rk_A)G = (h+rk_A)s^{-1}G

由于s=k1(h+rkA) mod ns=k^{-1} (h+rk_A) \ mod\ n

所以P=(h+rkA)kh+rkAG=kGP=(h+rk_A) \frac {k}{h+rk_A}G = kG

ECDSA 实践

假设现在有 A 和 B 需要通信

已知信息

  • 椭圆曲线E29(4,20):y2=x3+4x+20 mod 29E_{29}(4,20): y^2=x^3+4x+20 \ mod\ 29
  • 基点G=(2,6)G=(2, 6)GG的阶n=37n=37
  • 消息h=Hash(message)=88h=Hash(message) = 88

A 签名

  • [1,36][1,36]随机选择一个整数 7 作为私钥,则公钥H=kG=7(2,6)=(3,28)H=kG=7(2,6)=(3,28)
  • [1,36][1, 36]随机生成一个整数k=11k=11
  • 计算P=kG=11(2,6)=(16,2)P=kG = 11(2, 6) = (16,2)
  • 计算r=xP mod n=16 mod 37=16r=x_P\ mod\ n = 16 \ mod\ 37 = 16
  • 计算s=k1(h+rkA) mod n=k1(88+167) mod n=200k1 mod 37=20027 mod 37=35s = k^{-1} (h+rk_A) \ mod\ n = k^{-1}(88+16*7) \ mod\ n=200k^{-1} \ mod \ 37 = 200 * 27 \ mod\ 37 = 35
  • 发送(r,s)(r, s) 、A 的公钥HAH_A、消息hh 给 B

B 验证签名

  • 计算u1=s1h mod n=1888 mod 37=30u_1=s^{-1}h \ mod \ n = 18 * 88 \ mod\ 37=30
  • 计算u2=s1r mod n=1816 mod 37=29u_2 = s^{-1}r \ mod \ n = 18 * 16\ mod\ 37 = 29
  • 计算R=u1G+u2HA=30(2,8)+29(3,28)=(16,2)R = u_1G + u_2H_A = 30(2, 8) + 29(3, 28) = (16, 2)
  • 计算 xR mod n=16 mod 37=16=rx_R \ mod\ n = 16 \ mod\ 37 = 16 = r, 说明签名合法

secp256k1

secp256k1 是一条特定的椭圆曲线,椭圆曲线方程中 a =0, b = 7,故方程为y2=x3+7y^2 = x^3 + 7。曲线图如下:

有限域为GF(p)GF{(p)}

p=225623229282726241p=2^{256} - 2^{32}-2^{9}-2^8-2^7-2^6-2^4-1

= 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f

基点

G=(0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798, 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8)

GG的阶

n=22564324203865659656852420866394968145599n = 2^{256}-4324203865659656852420866394968145599

=0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141

[1, n-1] 随机取一个数kk作为私钥,则公钥H=kGH=kG

总结:

  • ecc: 如何生成公私钥
  • ecdh:通信双方如何生成相同的加密秘钥
  • ecdsa:对通信的消息如何签名才能确保消息没有被篡改
  • secp256k1:特定的椭圆曲线

参考