密码学基础2:椭圆曲线密码学原理分析

3,093 阅读19分钟
原文链接: www.jianshu.com

之前写过一篇文章分析过 RSA 算法原理后,想了解下更复杂点的椭圆曲线密码学原理(Elliptic Curve Cryptography,ECC),于是有了这篇文章。基于椭圆曲线的密码体系已经在密钥交换(如ECDHE)和数字签名(ECDSA)中得到广泛应用,如比特币就在其数字签名算法中用到了椭圆曲线。相较于 RSA,椭圆曲线密码体系可以使用更短的 key 达到更高的安全性。本文主要参考资料 elliptic-curve-cryptography-a-gentle-introduction, 其他诸多参考附在文末。如有错漏,恳请指正。

1 椭圆曲线概述

首先要说明的一点是,椭圆曲线不是椭圆。椭圆方程是下面这样的:

E = \{(x, y) \in \mathbb{R}^2 \ | \frac{x^2}{a^2} + \frac{y^2}{b^2} = 1\} \quad (椭圆)

而通常我们讨论的椭圆曲线的曲线方程是一个二元三次方程,它有多种形式,在椭圆曲线密码体系中,最常用的是如下的Weierstrass通用式(curve25519等其他类型的椭圆曲线本文不讨论):

E = \{(x, y) \in \mathbb{R}^2 \ | y^2 = x^3 + ax + b, \ 4a^3 + 27b^2 \neq 0\} \quad (椭圆曲线)

之所以取名叫椭圆曲线,是因为该曲线方程跟求椭圆弧长的积分公式相似。从曲线方程和图像易知,椭圆曲线关于X轴对称。判定式不等于零是为了椭圆曲线不存在奇异点,即处处光滑可导,这样才能进行椭圆曲线上的加法运算。下面是一些适合用于加密的椭圆曲线,其中 b=1, a \in \{2, 1, 0, -1, -2, -3 \}

一些合法的椭圆曲线

2 数学基础

椭圆曲线加密算法涉及数学中的群论、有限域等内容,这节简要介绍下相关数学理论。亦可以跳过直接看第3节,遇到相关名词再查阅即可。

2.1 群 (Group)

在讨论群之前,先说说集合。集合简单来说就是把一堆东西放在一起,如自然数集合。当然光有一堆东西还不够,东西之间相互作用才能更好的描述大千世界。于是,自然数集合通过加减运算衍生出整数集合、整数集合经过乘除又可以衍生出有理数,而后通过无理数的加入又衍生出实数集合、负数开方引入了复数集合。群则是集合和一个二元运算。

群: 是一个集合 G 连同一个二元运算 \cdot 表示为 (G, \cdot)。要成为一个群,该集合和运算需要满足如下4个要求:

  • 封闭性:对于 G 中任意的 ab,运算 a \cdot b 的结果也在集合 G 中。
  • 结合律:对于 G 中任意的 a,b,c,等式 (a \cdot b) \cdot c = a \cdot (b \cdot c) 成立。
  • 单位元:G 中存在一个元素 e,对于 G 中任意元素 a,等式 e \cdot a = a \cdot e = a 成立。
  • 逆元:对于 G 中任意元素 aG 中都存在另一个元素 b,使得 a \cdot b = b \cdot a = e,其中 e 是单位元。

而如果再满足交换律,则该群就被称为是一个阿贝尔群。

  • 交换律:对于 G 中的任意元素 a, b,等式 a \cdot b = b \cdot a 成立。

根据群的定义,整数的加法运算 (\mathbb{Z}, +) 就是一个群,而且还是一个阿贝尔群。而自然数的加法运算 (\mathbb{N}, +) 就不是一个群。整数加法运算构成群,因为它满足群的定义:整数加法的封闭性、结合律、交换律都成立。整数加法运算中单位元是 0。所有整数 n 都有加法逆元 -n。

在密码学中一般都需要一个有限的群,定义如下:

有限群: 如果一个群里的元素有限的,则称该群为有限群,群中元素数目称为群的阶。群 (G, \cdot) 的阶用记号 |G| 表示。

2.2 域 (Field)

为了使一个结构同时支持四种基本算术(即加减乘除),我们需要一个包含加法和乘法群的集合,这就是域。当一个集合为域的时候,我们就能在其中进行基本算术运算了。

F 是具有下面特性的元素集合:

  • F 中所有元素形成一个加法群,对应群的运算是 +,单位元为 0,对于元素 a,加法逆元表示为 -a
  • F 中除0外的所有元素构成一个乘法群,对应群的运算是 \times,单位元是 1。对于元素 a,乘法逆元表示为 a^{-1}
  • 对 F 中的元素混合使用这两种群操作时,分配律始终成立。即对所有的 a,b,c \in F,都有 a(b+c) = (ab) + (ac)

所以域中元素只要形成加法群和乘法群并满足分配律就行,因为群中元素都有逆元,减法/除法可以转换为加/乘元素的逆元实现。实数集合 \mathbb{R} 是一个域,加法群中单位元是 0,每个实数 a 都有加法逆元 -a,乘法群中单位元是 1,每个非零实数都有乘法逆元 1/a。而整数集合就不是域,因为大部分元素没有乘法逆元,不能构成一个乘法群。

在密码学中,通常只对有限元素的域感兴趣,这种域称为有限域(Finite Field)。有限域中我们经常用到的是素数域,所谓素数域,就是阶为素数的有限域。比如当 p 为素数时,整数环 \mathbb{Z}_p 就是一个素数域,可以记作 \mathbb{F}_p。在素数域 \mathbb{F}_p 中进行算术运算,需要遵守整数环的规则,即加法是模 p 加法,而乘法是模 p 乘法。

整数环 \mathbb{Z}_p 由下面两部分构成:

  • 集合 \mathbb{Z}_p = \{0, 1, 2, ..., p-1\},共 p 个元素。
  • 集合中两种操作 + (模加法)和 \times (模乘法),即对于所有的 a,b \in \mathbb{Z}_m ,满足:
    • a + b \equiv c(mod \ p), \ c \in \mathbb{Z}_p
  • a \times b \equiv d(mod \ p), \ d \in \mathbb{Z}_p

例如对于 \mathbb{F}_{23} 有:

  • 加法: (18+9) \ mod \ 23=4
  • 加法逆元: -5 \ mod \ 23 = 18,因为 (5+(-5)) \ mod \ 23 = (5 + 18) \ mod \ 23 = 0
  • 乘法: 4⋅7 \ mod \ 23=5
  • 乘法逆元:9^{-1} \ mod \ 23 = 18,因为 (9 \times 9^{-1}) \ mod \ 23 = (9 \times 18) \ mod \ 23 = 1

3 椭圆曲线中的群论

椭圆曲线上的点经过一种特定的加法运算可以让椭圆曲线在实数域构成一个群。

3.1 点加法

无穷远点:定义一个无穷远点 O,即经过椭圆上任意一点的与X轴垂直的直线都经过该点。可能有人疑惑垂直于X轴的直线是平行线,为啥可以定义为都经过 O 点?因为在非欧几何中,可认为平行线在无穷远处会交于一点。

椭圆曲线点加法:椭圆曲线上经过 PQ 两个点的直线与椭圆曲线的交点记作 R = P ⋄ Q,根据定义有 P ⋄ Q = Q ⋄ P 以及 O⋄ (O⋄ P) = P。继而定义椭圆曲线点加法:P \bigoplus Q = O ⋄ (P ⋄ Q),即为经过点 P⋄Q 且与 X 轴垂直的直线与椭圆曲线的另外一个交点,

点加法定义 单位元

椭圆曲线群:定义为椭圆曲线在实数域上的点集以及点加法 (E, \bigoplus)

  • 封闭性:元素是椭圆曲线上的点,且根据加法定义,加法运算得到的点都在椭圆曲线上,满足封闭性。

  • 单位元:选取无穷远点作为单位元,记为 O,易证得 O \bigoplus P = P \bigoplus O = P。(因为 O \bigoplus P = O ⋄ (O ⋄ P) = P)。

  • 逆元:因为椭圆曲线过于X轴对称,P(x, y) 的关于 X 轴对称的点 P^{'}(x, -y) 就是 P 的逆元。因为 P \bigoplus P^{'} = O ⋄ (P ⋄ P^{'}) = O ⋄ O = O

  • 交换律: P \bigoplus Q = O ⋄ (P ⋄ Q) = O ⋄ (Q ⋄ P) = Q \bigoplus P

  • 结合律: (P \bigoplus Q) \bigoplus R = P \bigoplus (Q \bigoplus R),通过几何作图可以验证得到的两个点确实相同,更严格的证明需要用到 [Cayley–Bacharach theorem],即假设两条三次曲线有9个交点,如果第三条三次曲线经过前两条三次曲线的8个交点,那么它也必定通过第9个交点。

(P+Q)+R P+(Q+R)

由此可知,椭圆曲线上的点在椭圆曲线加法运算上构成了一个阿贝尔群。增加了单位元后,椭圆曲线方程改为:

E = \{(x, y) \in \mathbb{R}^2 \ | y^2 = x^3 + ax + b, \ 4a^3 + 27b^2 \neq 0\} \ \bigcup \ \{ O \}

由定义可知,P \bigoplus Q = O ⋄ (P ⋄ Q) = O ⋄ R = -R,所以,最终加法只需要计算交点 R 的逆元 -R 即可。几种特殊情况说明:

  • 1)如果 P, Q 不是切点且不是互为逆元,则有第三个交点 R,故 P \bigoplus Q = -R
  • 2)如果 P 或者 Q 是切点,则 PQ 就是椭圆曲线的一条切线。假如 Q 是切点,则有 Q \bigoplus Q = -P
  • 3)如果 PQ 连线垂直于X轴,即 P = -Q,则跟曲线没有第三个交点,可以认为是交于无穷远点 O,故而 P \bigoplus Q = O
  • 4)如果 P = Q,则过它们的直线就是椭圆曲线过点 P 的切线,该直线一般来说跟椭圆曲线有另一个交点 R。如果恰好该切线如图4这样跟曲线没有其他交点,则可以认为交点为 O,即此时 P \bigoplus P = O
特殊情况说明

3.2 代数加法

上一节定义了椭圆曲线几何上意义的点加法,需要转换为代数加法以方便计算。要注意的是,这并不是两个点的坐标简单相加

假设直线 PQ 的斜率 m,然后将直线方程 y=mx+c 代入曲线可以得到: (mx+c)^2 = x^3 + ax +b, 转换成标准式,根据韦达定理 x_P + x_Q + x_R = m^2,即而可求得 R(x_R, y_R),想了解具体推导过程的可参见 [cubic-equations]

x_R = m^2 - x_P - x_Q
y_R = y_P + m(x_R - x_P)

斜率 m 计算需要区分两种情况,当 P=Q 时求椭圆曲线在 P 点的切线斜率(求导)即可:
m = \frac{y_Q - y_P}{x_P - x_Q} \quad (P \neq Q)
m = \frac{3x_P^2 + a}{2y_P} \quad (P = Q)

可以简单验证,比如椭圆曲线是 y^2 = x^3 - 7x + 10,P=(1,2), Q=(3,4),通过参考资料1的 [可视化工具] 可得 P \bigoplus Q = -R = (-3, 2)。容易验证,与代数加法公式计算结果一致。

m = \frac{y_Q - y_P}{x_P - x_Q} = \frac{4-2}{3-1} = 1
x_R = m^2 - x_P - x_Q = 1^2 - 1 - 3 = -3
y_R = y_P + m(x_R - x_P) = 2 + 1(-3-1) = -2

对于特殊情况P, Q中有一个是切点的情况,如 P=(-1, 4), Q=(1, 2),计算方式不变,易得 P \bigoplus Q = (1, -2)。而对于特殊情况 P = Q,采用切线斜率亦可验证公式正确。

3.3 标量乘法

在实际加密算法中,我们通常需要多次通过椭圆曲线加法来实现一次加密,如下图所示:

标量乘法

图中打点的过程就是:

A \bigoplus B = C \to A \bigoplus C = D \to A \bigoplus D = E

而在实际加密算法中,我们常常是使用一个点自己叠加,即初始直线变成椭圆曲线的切线即可,像下面这样:

A \bigoplus A = B \to A \bigoplus B = C \to A \bigoplus C = D \to ...

我们定义对一个点 P 进行 n 次加法得到 nP,称之为标量乘法。如前面例子中 B=2A,C=3A,D = 4A

nP = \underbrace { P \bigoplus P \bigoplus ... \bigoplus P}_{n \ times}

不过,当 n 很大时,执行 n 次加法需要 O(n) 时间,效率有问题。因为椭圆曲线在实数域构成了加法群,于是可以通过 [Double-and-add] 算法进行优化。比如 n=151,其二进制表示为 10010111_2,通过优化只要7次倍乘和4次加法计算即可,时间复杂度降到 O(log\ n)。这是一个很好的单向函数,正向计算容易,而反向和蛮力计算复杂。

151 P = 2^7 P \bigoplus 2^4 P \bigoplus 2^2 P \bigoplus 2^1 P \bigoplus 2^0 P

Q = nP,则 Q 作为公钥,n 为私钥。如果要破解该密钥,问题就是 "Q = nP,如果已知 P 和 Q,如何求解 n"? 由于在实数域上曲线连续,可能会更容易找到一些规律进行破解。此外,实数域上数值无确界、浮点数等问题而导致计算效率问题,在实际应用中常将椭圆曲线限制到一个有限域内,将曲线变成离散的点,这样即方便了计算也加大了破解难度。

4 有限域椭圆曲线

4.1 点加法

前面提到为了安全性和便于实现,需要将椭圆曲线限制到一个有限域内,通常用的是素数域 \mathbb{F}_p(即对于点 P = (x_P, y_P), x_P, y_P \in \{0, 1, ..., p-1\}, p 为素数)。于是破解就会变成一个离散对数问题,这比连续曲线上的对数问题会难很多。素数域下椭圆曲线定义如下:

E = \{(x, y) \in (\mathbb{F_p})^2 \ | y^2 \equiv x^3 + ax + b(mod \ p), \ (a, b \in \mathbb{F}_p, 4a^3 + 27b^2 \not \equiv 0(mod \ p))\}\bigcup \ \{ O \}

下面是曲线 y^2 \equiv x^3 - 7x + 10(mod \ 19)y^2 \equiv x^3 - 7x + 10(mod \ 97) 的图像。可以发现,椭圆曲线变成了离散的点,且关于 y = p/2 对称。

有限域椭圆曲线

定义 \mathbb{F}_p 上椭圆曲线点加法 P \bigoplus Q = -R 如下,公式跟实数域上相比只是多了模 p 操作。

x_R = (m^2 - x_P - x_Q) \bmod p
y_R = [y_P + m(x_R - x_P)] \bmod p

斜率 m 计算同样分两种情况:
m = [(y_Q - y_P)(x_P - x_Q)^{-1}] \bmod p \ (P \neq Q)
m = [(3x_P^2 + a)(2y_P)^{-1}] \bmod p \ (P = Q)

椭圆曲线在素数域 \mathbb{F}_p 上的点加法依然构成阿贝尔群。单位元依旧是无穷远点,元素 R=(x_R, y_R) 的逆元变成 -R = (x_R, -y_R \bmod p)。而交换律、结合律、封闭性则可以通过素域上的模加法、模乘法来证明。实数域的椭圆曲线点加法定义是有明确几何意义的,从几何上好证明。而椭圆曲线在 \mathbb{F}_p 就没有明显的几何意义了,观察可发现 P, Q, R 三点满足 ax + by + c \equiv 0(mod ~ p),群律的证明过于繁琐,略去。

以前面曲线为例,P = (1, 2), Q=(3,4),则有 P + Q = -R = (16, 2),且 R-R 都在椭圆曲线上。从图形上看,P, Q, R 在直线 x-y+1 \equiv 0(mod ~19) 上。

m = [(4-2)(3-1)^{-1}] \bmod 19 = 1
x_R = (1^2 - 1 - 3) \bmod 19 = -3 \bmod 19 = 16
y_R = [2 + 1(16 - 1)] \bmod 19 = 17 \bmod 19 = 17
P + Q = -R = (16, -17 \bmod 19) = (16, 2)

有限域点加法

4.2 椭圆曲线群的阶

在有限域下,椭圆曲线加法群的元素是有限的,元素数目就是群的阶。

如椭圆曲线 y^2 \equiv x^3 - 7x + 10(mod ~ 19),其在素数域 \mathbb{F}_{19} 中元素有 (1, 2), (1, 17), (2, 2)...,阶为24(23个素数域中的点 + 1个无穷远点),如果 p 很大的话,则通过蛮力计算阶是很难的,好在使用 [Schoof算法] 可以在多项式时间内计算出群的阶。计算椭圆曲线在有限域上点的数目可以参见 [Counting points on elliptic curves]

Schoof算法运用了 Hasses 定理。Hasses定理给出了椭圆曲线在 \mathbb{F}_p 的阶的范围,可以看出,当 p 很大时,阶跟 p 的值是比较接近的。

Hasses 定理:令 E\mathbb{F}_p 上的椭圆曲线,E 上的点的数量 |E| 满足如下条件:
p + 1 - 2\sqrt{p} \leq |E| \leq p + 1 + 2\sqrt{p}

4.3 循环子群

跟实数域一样,在素数域里面也是选取一个点 P,然后计算倍乘 nP 作为公钥。还是以 y^2 \equiv x^3 - 7x + 10(mod ~ 19) 为例, P=(1,2),我们采用素数域下新的计算公式计算 nP

0P = O, \ 1P = (1, 2), \ 2P = (18, 15), \ 3P = (9, 12),\ ...
8P = O, \ 9P = (1, 2), \ 10P = (18, 15),\ 11P=(9, 12) \ ...

可以发现 kP = (k \bmod 8)P,即 P 的标量乘法得到的点集是原椭圆曲线群的一个子集,则它是原椭圆曲线群的一个子群,而且是循环子群。子群中元素个数称为子群的阶(示例子群的阶为8),点 P 称为该子群的基点或者生成元。循环子群是椭圆曲线密码体系的基础,我们期望子群中元素越多越好,如何找到一个合适的子群尤为重要。

首先要解决一个问题,就是已知 \mathbb{F}_p 下的椭圆曲线上的点 P,如何求得 P 的倍乘运算后生成的子群的阶? 根据拉格朗日的群论定理,子群的阶是父群的阶的约数。求解曲线上点 P 生成的子群的阶可以用下面方法:

  • 首先,使用Schoof算法求得椭圆曲线群的阶 N
  • 找到 N 所有的约数。
  • N 所有的约数 n,计算 nP
  • 其中 nP = O 中最小的 n 就是子群的阶。

以示例曲线为例,父群的阶是 24,则以曲线上的点生成的子群的阶只能是 1,2,3,4,6,8,12,24。对于点 P = (1,2),P \neq O, 2P \neq O, ..., 8P = 0,故其生成的子群的阶就是 8,而点 Q = (3, 4) 生成的子群的阶则正好是 24。

4.4 寻找基点

在加密算法中,我们期望找到一个阶高的子群。不过,通常不是先去找个基点,然后计算子群的阶,因为这样过于不确定,算法上不好实现。相反地,先选择一个大的子群阶,然后再找生成该子群的一个基点就容易多了。

前面提到,子群的阶 n 是父群的阶 N 的约数,即有 N = nh \to h = N/n,h 是一个整数,我们称之为子群的余因子(cofactor)。因为 nP = O,所以有:

NP = n(hP) = O

通常会选择一个素数作为子群的阶,即 n 是素数。可以发现,点 G=hP 生成了阶为 n 的子群(G=hP=O 除外,因为这个子群的阶为1),不等于 O 的点 G 就是我们寻找的基点。具体步骤如下:

  • 1)计算椭圆曲线的阶 N
  • 2)选择子群的阶 nnN 的约数,且要选择素数。通常是越大越好,如 n = N
  • 3)计算余因子 h = N/n
  • 4)从椭圆曲线随机选取一个点 P,计算 G=hP
  • 5)如果 G=O,则返回第 4 步重新选一个点计算。

需要注意,上面算法里的 n 必须是素数,否则计算的基点 G 生成的子群的阶可能是 n 的约数而不是 n,不符合要求。以曲线 y^2 \equiv x^3 - x + 1(mod ~ 29)为例,N = 37,我们选择 n = 37,则 h = 1,随机选取一个点 P = (3, 5),计算 G=hP=P=(3,5),恰好满足要求。

4.5 域参数

如前所述,椭圆曲线加密算法工作在素数域下的椭圆曲线循环子群中,需要的域参数(Domain Parameter)包括 (p, a, b, G, n, h)

  • p: 素数域的大小。
  • a, b: 椭圆曲线 y^2 = x^3 + ax + b 的系数。
  • G:生成子群的基点。
  • n:子群的阶。
  • h:子群的余因子。

如比特币用来做数字签名中采用的椭圆曲线 [secp256k1] 的域参数如下:

  • p = 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F = 2^{256} - 2^{32} - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
  • a = 0, b = 7,即曲线方程是 y^2 = x^3 + 7
  • G = (0x79BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9 59F2815B 16F81798,
    0x483ADA77 26A3C465 5DA4FBFC 0E1108A8 FD17B448 A6855419 9C47D08F FB10D4B8)
  • n = 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141
  • h = 1

5 实例分析

5.1 ECDH(E)

在 ECDH 跟(Diffie–Hellman Key Exchange)有点类似,只是不再通过简单的模幂运算,而是通过素数域下的椭圆曲线的标量乘法来实现。流程如下:

  • Alice 和 Bob 生成各自的公私钥。假设 Alice 的私钥是 d_A,公钥则为 H_A=d_AG,Bob 的则是 d_BH_B = d_BG。他们用的同一个基点 G、同一个整数有限域,同一条椭圆曲线。
  • Alice 和 Bob 通过不安全的信道交换公钥 H_AH_B
  • Alice 计算 S = d_AH_B,Bob 计算 S = d_BH_A,共享密钥就是 S。对称加密算法 AES 或者 3DES 只用 S 的一个坐标如x坐标作为密钥即可。
    S = d_AH_B = d_BH_A = d_Ad_BG
  • 要想破解密钥就好比"已知 G,aG,bG 求 a 和 b?",当 ab 很大的时候,破解是很困难的,这也被称为椭圆曲线的离散对数问题,即 ECDLP。
ECDH 示意图

ECDHE (Ephemeral ECDH) 与 ECDH 不同之处在于,它的公私钥并不固定,而是每次会话临时生成,这样就能具有前向安全性,实际项目中也用的更多。

5.2 ECDSA

ECDSA 是 DSA 算法的变种,常用于数字签名。Alice 通过椭圆曲线算法生成公私钥 d_A, H_A,对要签名的消息通过哈希算法生成摘要 z (z为整数),然后 Alice 用私钥 d_A 按照下面步骤对摘要 z 生成签名。 Bob 通过公钥 H_A 验证签名。

生成签名

  • 1)Alice 选取一个随机数 k,其中 k \in \{1, 2, ...n-1\},n为子群的阶。
  • 2)计算 P = kG,G 是曲线的基点。
  • 3)计算 r = x_P \bmod n,如果 r = 0,则回到第1步重新选择一个 k 重试。
  • 4)计算 s = k^{-1}(z + rd_A) \bmod n。如果 s = 0,则回到第1步重新选择一个 k 重试。
  • 5)(r, s) 就是最终的签名对。

校验签名

  • 1)计算 u_1 = s^{-1}z \bmod n
  • 2)计算 u_2 = s^{-1}r \bmod n
  • 3)计算 P = u_1G + u_2H_A
  • 4)如果 x_P \bmod n = r,则签名有效。
ECDSA 示意图

证明

因为 H_A = d_AG,于是:

P = u_1G + u_2H_A = u_1G + u_2d_AG = (u_1 + u_2d_A)G
= (s^{-1}z + s^{-1}rd_A)G = s^{-1}(z + d_A)G

而之前定义有:s = k^{-1}(z + rd_A) \bmod n \Rightarrow k = s^{-1}(z + rd_A) \bmod n

因此 P = s^{-1}(z + d_A)G = kG,这与生成签名时一致,故而证明完毕。

实例分析

还是以y^2 \equiv x^3 - x + 1(mod ~ 29)为例,n=37,选取 G=(3,5)。选择 d_A=7,则 H_A = d_AG = 7G = (27, 16)。假设要签名的消息摘要 z = 88。经过计算发现,验证成功。

生成签名:

  • 选择随机数 k = 11
  • P = kG = 11G = (2, 6)
  • r = x_P \bmod n = 2 \bmod 37 = 2
  • s = k^{-1}(z + rd_A) \bmod n = 27(88 + 2*7) \bmod 37= 16
  • 所以签名对就是 (r, s) = (2, 16)

验证签名:

  • u_1 = s^{-1}z \bmod n = 7*88 \bmod 37 = 24
  • u_2 = s^{-1}r \bmod n=7*2 \bmod 37 = 14
  • P = u_1G + u_2H_A = 122G = (2, 6)
  • x_P \bmod n = 2 \bmod 37 = 2 = r

注意事项

  • ECDSA 中用的子群的阶 n 必须是素数,否则 k^{-1} \bmod n 可能不存在。
  • 选择 k 的随机数生成器一定要设计好,不能有漏洞。如果随机数生成不够随机或者可预测,则可能出现两个相同的随机数,继而会有两个相同的签名,如 r_1 = r_2。则根据公式可以计算出 k,继而就能计算出私钥 d_A 了。

(s_1 - s_2) \bmod n = k^{-1}(z_1 - z_2) \bmod n \Rightarrow k = (z_1 - z_2)(s_1 - s_2)^{-1} \bmod n

s = k^{-1}(z + rd_S) \bmod{n} \Rightarrow\ \ d_S = r^{-1} (sk - z) \bmod{n}

5.3 TLS密钥交换

TLS里面加密用的 Cipher Suite有很多,常见的如 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,意思是: 使用ECDHE进行密钥交换,RSA做服务验证,SHA256用于签名摘要生成,AES128-GCM用作对称加密。

现在 TLS 密钥交换和签名通常有三种方式:RSA,ECDHE_RSA 以及 ECDHE_ECDSA,区别如下。关于 TLS 的具体流程分析,这篇文章 [The Illustrated TLS Connection] 一定要隆重推荐下。

  • RSA: 密钥交换无需数字签名,不过由于其没有前向安全性,已经用的不多。
  • ECDHE_RSA:使用ECDHE密钥交换,RSA数字签名,目前使用比较广泛。在ECDHE中,客户端和服务端都会生成各自的椭圆曲线密钥对,服务端给客户端发送它的椭圆曲线公钥的时候使用RSA证书私钥做数字签名,客户端使用RSA证书中的公钥验证签名。
  • ECDHE_ECDSA:使用ECDHE密钥交换,ECDSA数字签名,需要使用 ECC 证书。

6 总结

本文介绍了椭圆曲线密码学原理。通过定义有限域下面椭圆曲线的一种点加法,并证明该椭圆曲线在实数域和素数域下该点加法都构成阿贝尔群。由此定义了标量乘法,Q = kP,通过随机数生成算法随机选择一个正整数 k 作为私钥,从而得到公钥 Q 和 私钥 k。文章最后简要分析了 ECDHE 和 ECDSA 的数学原理和应用。

如文中所述,椭圆曲线的构建和选择需要注意如下几点:

  • 素数域 p 和 子群的阶 n 不能太小,否则会有破解风险,建议 256 位以上。
  • 素数域大小 p 和 n 需要满足 p \neq hn,否则会有风险,详见 [Weak Curves In Elliptic Curve Cryptography]
  • ECDSA 的椭圆曲线子群的阶 n 必须是素数,且随机数生成算法一定要够随机不可预测,否则会有泄露私钥的风险,原理前文已经说过。如 [这篇文章] 就描述了如何使用随机数碰撞获取私钥恢复以太坊钱包的。
  • 美国国家安全局曾经推荐使用 secp256r1,它的曲线方程的系数比 secp256k1 复杂许多。然而由于该曲线的设计过程不透明,很早就被怀疑有后门,在棱镜门后怀疑声更甚。巧的是,中本聪在设计比特币的时候也恰好绕过了使用该曲线。这里有篇文章 [a-tale-of-two-elliptic-curves] 介绍了这两种曲线。棱镜门之后,Daniel J. Bernstein 教授早年设计的 curve25519 曲线大火,该曲线系数来源明确,也已经被越来越多的机构采纳。

参考资料