曲线上的“加密货币”(二)

字数 3432阅读 377

上一篇文章(《曲线上的“加密货币”(一)》)介绍了Bitcoin网络中对ECC的使用,说明了支付时解锁脚本与锁定脚本的执行过程,结尾处留了几个问题,这些问题的答案就在椭圆曲线加密的机制中。

公钥加密体系中,最重要的就是通过一个数学难题生成密钥对,这个数学难题使得从私钥生成公钥很容易,而从公钥反推出私钥很难。传统的公钥加密体系(如RSA)中,使用的数学难题是整数的因式分解,即两个素数求其乘积很容易,而从其乘积通过因式分解找到对应的两个素数因子很难。椭圆曲线加密中使用的数学难题则是椭圆曲线在有限域上的离散对数问题。

(......前方高能预警,一大波数学概念和公式来袭......)

迪卡尔建立解析几何后,我们都知道直线、曲线等几何对象可以用代数方程表式,如直线可以由一次方程表示,圆锥曲线可以由二次方程表示:
直线:

椭圆:

那椭圆曲线的方程式是什么样的呢?它可以由三次方程表示:

它对应的图形大致是(a、b的值不同时,形状将不一样):

从图中看,椭圆曲线与椭圆相差很远,为什么叫它椭圆曲线呢?实际上是因为椭圆曲线的方程式正好是椭圆周长公式中积分表达式分母的平方:

为了进一步理解椭圆曲线上点与点之间的关系,数学上抽象了椭圆曲线的(Group),规定:

  1. 群里的元素均是椭圆曲线上的点;
  2. 群的零元是无穷远点;
  3. 群中元素的逆元是该点在曲线上关于x轴的对称点;
  4. 群中元素P、Q和R如果在一条直线上,则 P + Q + R = 0。

由于 4 中P、Q和R在一条直线上与其顺序无关,故很容易证明群中的加法运算满足交换律和结合律,因而椭圆曲线上的群是一个加群,或者Abel群,即它的加法运算与我们实数的加法形式完全一样。那么椭圆曲线群中的加法是什么样的呢?根据上述第 4 条:

即点 P 与点 Q 相加的结果是点 R 在群中的逆元,我们在 3 中定义群中的逆元是点关于 x 轴的对称点,所以 P + Q 就是指连接 P 和 Q 的直线与曲线的交点R关于 x 轴的对称点R',如图所示:

特别地,当 P = Q 时,P 与 Q 的连线即为曲线在 P 点的切线;当 P = -Q 时,P、Q的连线与x轴垂直,其与曲线的交点在无穷远点, P + Q = 0;当 P = 0 或者 Q = 0 时,P 与 Q 的连线为 Q 或者 P 与无穷远点的连线,其与x轴垂直,故与曲线的交点位于 -Q 或者 -P,所以 P + Q = Q (P = 0) 或者 P (Q = 0)。

这样,椭圆曲线代数加法运算与实数的加法运算完全一致,而且与其几何意义完全对应起来。很自然地,我们得到群的点乘(或者标量乘法,Scalar multiplication):

其中n为自然数。它的几何意义如下:

即以点P作曲线的切线,切线与曲线相交于R(-2P),R 关于 x 轴的对称点即是点2P,在点2P处作切线,按相同方法可以找到点4P、8P等。如果连接点2P与P,直线与曲线相交于点-3P,其x轴的对称点是3P,如此循环下去可以得到点 nP。代数求解点R的坐标,就是求解直线方程与椭圆曲线的方程组,这在中学数学中反复练习过,这里不再赘述。定义完点乘运算后,我们就可以定义椭圆曲线的对数问题了:

已知曲线、点P 和 Q,如何求n。这是一个难题。当已经知道n和P的时候,我们通过上面的点乘运算,容易求得点Q。但知道P和Q,求n很难。就是说: 给了你一条曲线和起始点P,规定了每一次加P后点的位置,当告诉你最后点的位置时,你无法知道作了多少次加法,除非你遍历所有i*P(0<i<n),找到正好对应最后点位置的i值。

然而,当椭圆曲线应用到计算机加密领域时,不能在整个实数域来取点或者运算,而需将其“映射”到一个元素个数或者点的个数有限的集合中(离散化)。当我们对椭圆曲线方程两边对素数p取模时(模运算不展开说明了),就定义了一个有限域F(p):

这样,在F(p)中的曲线的点的个数就不再是无限多个了,而是有限个数N,它是有限域中曲线群的阶。在有限域上的曲线不再是连续的,而是分散的点,如图(可以通过链接演示椭圆曲线在实数域和有限域的加法和乘法):

一个有限域F(p)类似于一个有理数集合,有自己的加法、乘法、除法、单位元(1),零元(0),并满足交换率和分配率。值得注意的是,这里的p必须是素数,否则不能满足有限域内的所有元素均有乘法逆元素(multiplicative inverse),即不能实现除法。

显然,F(p)中的曲线仍然是一个加群,即上述连续实数域上的加法和点乘运算仍然适用,但不再有直观的几何意义了。特别地,在有限域F(p)中的曲线上点的点乘将呈现周期循环特性,即存在最小整数n,使得:

点集{0, G, ..., (n-1)G},构成了一个循环子群(Subgroup),n为该 子群的阶(Order),它是曲线在F(p)中的点的个数N的因子,点G即为该循环子群的生成点(Base Point)。需要注意的是,实际中确定一个子群的生成点时,是通过找到N的一个素数因子n(必须是素数,否则不能用于ECDSA,因为无法求乘法逆元素),即确定了子群的阶,然后计算子群的余子式(Cofactor)h=N/n,再从曲线上任选一点P,计算当满足h*P != 0时,G=hP,从而确定生成点。(想想为什么呢?提示: NP=0)

好了,到这里我们就可以确定一条ECC上用到的曲线了,它通过六个参量描述:

其中,p为定义有限域F(p)大小的素数,a、b为椭圆曲线方程的系数,n、h、G定义了曲线的一个循环子群,它的阶为n(即元素个数),余子式为h(即曲线的点个数与子群的点的个数的比值),生成点为G(即子群中的点为kG, 0<= k < n)。

那么在有限域上的数学难题与连续实数域上的数学难题有变化吗?基本上没有,只是引入了模运算,就是我们文章开始提到的离散对数问题,即已知T和子群中一点:

如何求得k的问题。这是一个难题,也是椭圆曲线能用于现代加密的原因。

到此,我们介绍了用于ECC的有限域F(p)中的椭圆曲线及其离散对数问题,自然地,可以根据离散对数问题来生成密钥对。

  1. 首先,从{0,1,...... ,n-1}中随机选择一个数 d 作为私钥;
  2. 然后,通过 Q=dG 计算出公钥Q。

生成完毕后的密钥对可以与DH密钥交换算法结合形成ECDH算法,密钥交换后可以用AES或者DES等加密,类似于TLS加密过程。由于“加密货币”中主要使用ECDSA,接下来主要介绍使用椭圆曲线生成的密钥对进行数字签名及验证签名的机制。

到此,我们已经回答了前文中提到如何从私钥生成公钥的问题。现在没有确切数学证明解上述离散对数问题是一个“难题”,但现有条件及算法均不可能在有效时间内求解,所以我们可以说从公钥破解私钥是很难的。在介绍完ECDSA后,我们就可以回答为什么前述的Android漏洞会导致私钥泄露了。

介绍ECDSA时,我们要请出Alice和Bob了。假如Alice根据上述椭圆曲线生成了私钥d(A)和公钥Q(A),她将向Bob发送消息m,并对该消息签名;Bob知道Alice的公钥Q(A),他收到Alice的签名消息后,要对该消息进行验证,看是否是Alice发送的和有没有被篡改。Alice和Bob均采用相同的椭圆曲线参数(p, a, b, n, h, G)。Alice发送签名消息时,将:

  1. 对消息m进行安全Hash(如SHA-2),然后截取Hash后的数据的左边n bit,得到一个整数z;
  2. 从 {0,1,...... ,n-1} 中安全随机地选择整数k;
  3. 计算点
  1. 计算

,如果 r=0,则回到步骤 2 重新计算;

  1. 计算

,k^-1便是 k mod n 的乘法逆元素;

  1. 如果s=0,再回到步骤 2 重新计算.

经过上述计算后,Alice得到了对消息m的签名(r, s),将该签名与消息m一并发送给Bob,Bob收到后将作如下验证:

  1. 验证收到的r和s是否在{0,1, ...... ,n-1}范围内;
  2. 按照和Alice相同的安全Hash函数对m进行Hash,并截取左边n位得到整数z;
  3. 计算
  1. 计算
  1. 计算点

,Q(A)为Alice的公钥;

  1. 如果r = x(p) mod n,则说明签名是真实的,否则签名或者消息被篡改。

通过几步代数替换,很容易证明上述验证过程:

可以看出,Bob计算出的P(x(p), y(p))与Alice计算出来的完全一样,如果传输过程中,r,s,m中有被篡改的或者s不是由Alice的私钥计算出来的,那上述等式不可能成立,Bob对签名的验证将失败。值得注意的是,签名中的r与选择的随机数是强相关的,它必须是密码学安全随机的,我们来看看如果这个k不变会发生什么:

  1. Alice对消息m1(对应的Hash摘要为z1),生成一个签名(r1, s1);
  2. Alice对消息m2(对应的Hash摘要为z2),生成一个签名(r2, s2);

Bob收到两次消息及签名后,可以这样做:

  1. 因为 k 是不变的,所以Alice在签名过程中计算的点 P(x(p), y(p))也是一样的,Blob收到的 r 也是一样的,即 r1 = r2;
  2. Bob计算:

容易得到:

将k代入:

可以得到:

这样,接收方Bob便窃取了Alice的私钥。所以在签名时保证k在密码学安全上的随机性是十分关键的。前述的Android漏洞就是其4.2版本之前的安全随机数生成器SecureRandom未初始化,ECDSA中选取随机数时不能保证其随机性,使得每次签名时用的k值一样,很容易被接收方反推出发送方的私钥。这种攻击方式就是旁路攻击(side attack)的一种。

Bitcoin网络中选择的曲线是secp256k1,即曲线子群阶 n 的长度为256 bit,在现有算法和计算能力下,采取正面碰撞破解,大致需要2^71(2的71次方)年。随着量子计算机的发展,通过量子计算有可能将计算时间缩短到可接受范围,但目前还没有实用的量子计算机,也许随着量子计算的发展,人们会找到新的加密方法。了解了ECC加密和签名的机制后,大家应该对Bitcoin网络的安全性有了合理的信心,那你会选择使用它吗?

推荐阅读更多精彩内容