新手上路:实数上的椭圆曲线和群论

新手上路:实数上的椭圆曲线和群论

本文节选自推文集《友好型入门:椭圆曲线密码学(Elliptic Curve Cryptography: a gentle introduction)》,作为史上最贱的数学题的拓展阅读。

原文出处:ANDREA CORBELLINI

翻译:镜子文明


【引子】

如果你听说过公共密钥密码学,那你应该也听说过ECC,ECDH或者ECDSA。其中,ECC就是椭圆曲线密码学首字母缩略词,后二者都是基于ECC的算法。

如今,在构建现代网络和IT世界的主流技术中,比如TLS(Transport Layer Security,安全传输层协议),PGP(Pretty Good Privacy,基于RSA的邮件加密系统)和SSH(Secure Shell,安全外壳协议)里面,我们都能够找到椭圆曲线加密系统的踪影。更不要说比特币和其它加密电子货币了。

在ECC普及之前,几乎所有公共密钥算法都用基于RSA、DSA和DH等使用模块计算的加密系统替代。RSA及其衍生算法在现在仍然十分重要,常常被用于辅助ECC算法。然而,相对于易于解释、易于一般性地理解并且易于粗要实现的RSA及其衍生算法来说,ECC的理论基础对多数人还是一个谜团(*注:RSA理论基础简单来说就是因式分解两个大素数的乘积非常困难)。

通过一系列的博客推文(*注:我只翻译了椭圆曲线入门介绍,后续见原文链接),我将用友好的方式向你介绍椭圆曲线密码学的世界。我的目标不是提供一个完整详细的ECC导论(网上这种文章俯拾皆是),而是把冗长数学证明和枯燥实现细节的功夫节省下来,直接带你简要总观ECC,然后理解它为什么能确保加密安全。我也会以可视交互工具和脚本的形式提供一些有意思的例子,帮助你把弄这个玩意。

具体来说,我展开的主题如下

1.实数上的椭圆曲线和群论(本篇)

2.有限域上的椭圆曲线和离散对数问题

3.密钥对生成和两个ECC算法:ECDH和ECDSA

4.破解ECC安全性的算法以及与RSA的对比。

为了能够理解本文内容,你需要了解一点集合论基础、几何学和模运算,并且熟悉对称和不对称加密。最后,你需要清晰地认识到,密码学中什么是简单问题,什么是困难问题,它们在密码学中扮演什么样的角色。

准备好了吗?正文开始!


【椭圆曲线】
首先,我们需要知道,到底什么才是椭圆曲线呢?Woldram MathWorld给出了精彩而完整的定义。但考虑到我们的初衷,我们可以简化理解,它就是由这个方程描述的曲线:

y^2=x^3+ax+b

其中, 4a^3+27b^2≠0 (需要排除退化成奇异曲线的情况)。上述方程就是所谓的椭圆曲线魏尔斯特拉斯一般形式。

椭圆曲线的不同形状(b=1,a从2开始递减到-3)
退化的奇异曲线类型:左边是一条带尖点(cusp)的曲线(y^2=x^3);右边是一条自交的曲线(y^2=x^3-3x+2)。它们都不是有效的椭圆曲线。

随着 ab 取值的变化,椭圆曲线可能在平面上呈现不同的性状。不论是直观还是证明,我们都可以发现椭圆曲线是关于X轴对称的。

想要讲清椭圆曲线,我们还需要引入无穷远点(也被称为理想点)作为曲线的一部分。从现在开始我们将用符号 0 (零)表示无穷远点。

如果我们想明确地理解无穷远点,我们还需要进一步精炼椭圆曲线的定义,如下所示:
{{(x,y)∈R2 | y^2=x^3+ax+b, 4a^3+27b^2≠0} } ∪ { 0 }


【群】

数学里面的群是一类定义了二元运算(我们称之为加法,用符号+表示)的集合。如果想让集合 G 变成一个群,我们必须定义满足如下四条性质的加法:

1.封闭性:如果 a b 属于 G ,那么 a+b 也属于 G ;

2.结合律: (a+b)+c=a+(b+c) ;

3.存在单位元(*注:在二元运算中,单位元指与任意元素运算不改变其值的元素,以实数为例,乘法单位元为1,加法单位元为0) \theta 使得 a+ \theta= \theta+a=a ;

4.每个元素都存在逆元素,也即对于任意元素a存在b使得 a+b= \theta

如果我们添加第五条要求:

5.交换律: a+b=b+a

那么这个群就是阿贝尔群。

根据加法的一般定义,整数集Z是一个群(更确切地说,它是个阿贝尔群)。然而,自然数集N却并不是一个群,因为它不满足第四条性质。

群是一个好东西,如果我们能够证明那四条性质一直保持,那我们就可以无条件地得到其它一些性质。例如:单位元唯一,元素的逆唯一,也即:对于任意元素 a ,有且仅有唯一元素 b 使得 a+b=\theta (而且可以用 -a 表示 b )。在接下来的文章中,有关群的这些或其它事实将会向我们直接或间接地展现出它们的重要性。


【椭圆曲线的群律】

我们可以在椭圆曲线上定义一个群。具体地说,

群的元素是椭圆曲线上的点;

单位元 \theta 是无穷远点 0

点P的逆是它关于 x 轴的对称点。

加法通过如下法则定义:给定三个共线非零的点 P,QR ,它们的和为 P+Q+R=0

共线三点的和为0

既然根据最后一条法则,加法只需要三个共线的点,对顺序没有要求,也就是

P+(Q+R)=Q+(P+R)=R+(P+Q)=……=0

通过这种方式,我们已经直观地证明了我们的+算符同时满足结合律和交换律:我们得到了一个阿贝尔群。到此为止,还算完美。但现在问题来了,我们该怎么计算任意两个点的加法?


【几何加法】

万幸我们处理的是一个阿贝尔群,这样我们可以顺手地将 P+Q+R=0 变形为 P+Q=-R 。通过这种形式的等式,我们可以导出计算两点P和Q之和的几何方法:如果我们过 P,Q 做一条直线,这条直线将与曲线交于第三个点 RP,Q,R 三点共线的定义已经暗示了该曲线的这条性质)。如果我们取这个点的逆 -R ,那我们就得到了结果 P+Q

过P,Q作直线交曲线于第三个点R。R关于X轴的对称点-R就是P+Q的结果

这个几何方法很有效,但它还需要一点完善。具体地,我们需要回答几个问题:

1. P=0 或者 Q=0 怎么办?显然,我们不能作任何直线(无穷远点 0 不在 xy 平面上)。但既然我们已经把 0 定义为标准元,那对于任何点 P 或者 Q 来说,它们与 0 的和就是它们自身。

2. P=-Q 怎么办?在这种情况下,过两点的直线垂直于X轴不与曲线相交。但根据逆的定义,如果P是Q的逆,那么 P+Q=P+(-P)=0

*注:不严谨的理解,这条直线与椭圆曲线在无穷远点相交。

3.如果 P=Q 怎么办?在这种情况下,有无数条直线过这个点。这里事情就变得有点复杂了。但我们可以先构想一个 Q’ (Q’≠P) 。如果 Q’ 逐渐接近 P 点, PQ’ 会变成什么样?

随着两点越来越靠近,过两点的直线逐渐趋近于曲线的切线。

随着 Q’ 点逐渐趋近 P 点,过 P,Q’ 两点的直线也逐渐趋近曲线的切线。根据这个事实,我们能这样断言:过 P 点作曲线的切线与曲线交于另一点 RP+P=-R

4.如果 P≠Q ,但找不到第三点 R 怎么办?这种情况很像上一种。事实上,这种情况就是过 P,Q 的直线是曲线的切线(*这里的 Q 就是上一种情况里面的 R )。

如果直线仅有两个交点,那意味着它与曲线相切。

要想找到和的结果其实很简单,它就是其中一个点关于X轴的对称点。不妨设 P 点就是切点,在上一种情况,我们已经说明 P+P=-Q ,这个等式可以变成 P+Q=-P 。如果切点是 Q 点,正确的等式就变成了 P+Q=-Q

几何方法现在已经完备地覆盖了所有情形。用一支铅笔一块橡皮我们就能对任意椭圆曲线上的所有点作加法。如果你跃跃欲试,尽管参考HTML5/JavaScript visual tool ,我已经搭建了椭圆曲线和值计算的环境。


【代数加法】

如果我们想用计算机作加法,我们需要把几何方法改造成代数方法。将上述规则转化为一组方程看上去简单直接,但做起来就冗长乏味了,因为它需要解三次方程。基于这个理由,我直接把答案贴出来。

首先,让我避开那些恼人的极端情况。我们已经知道 P+(-P)=0 ,并且 P+0=0+P=P 。因此,在我们的方程中,不考虑这两种情况,仅仅考虑两个非零、非对称的点 P (x_{P},y_{P})Q (x_{Q},y_{Q}) 。如果 PQ 不重合 (x_{P}\ne x_{Q}) ,那么过两点直线的斜率就是:

m=\frac{y_{P}-y_{Q}}{x_{P}-x_{Q}}

与椭圆曲线的交点为第三点 R= (x_{R},y_{R})

x_{R}=m^2-x_{P}-y_{P}

y_{R}=y_{P}+m(x_{R}-x_{P})

或者等于

y_{R}=y_{Q}+m(x_{R}-x_{Q})

因此  (x_P,y_P)+(x_Q,y_Q)=(x_R,−y_R) (注意这些符号并且别忘了 P+Q=-R

如果我们想要检查这个结果是否正确,我们必须得检查R是否属于曲线而且 P,Q,R 三点共线。检查三点共线不足为虑,但检查 R 属于曲线就很烦躁了,因为我们要解一个三次方程,那真的一点都不好玩。

扔掉上面的问题,我们直接从例子入手:根据我们的可视化工具,给定曲线上的 P(1,2)Q(3,4) ,它们的和 P+Q=-R=(-3,2) 。让我们看看代入方程是否一致。 m=\frac{y_P-y_Q}{x_P-x_Q}=\frac{2-4}{1-3}=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\cdot(-3-1)=-2

或者 y_R=y_Q+m(x_R-x_Q)=4+1\cdot(-3-3)=-2

耶,对的!

既然这些方程即使在 P 或者 Q 是切点的时候都有效,那我们就试试 P(-1,4)Q(1,2)

m=\frac{y_P-y_Q}{x_P-x_Q}=\frac{4-2}{-1-1}=-1

x_R=m^2-x_P-x_Q=(-1)^2-(-1)-1=1

y_R=y_P+m(x_R-x_P)=4+(-1)\cdot[1-(-1)]=-2

我们得到了结果 P+Q=(1,-2) ,与可视化工具给出的一模一样。

P=Q 的情况需要一点特别对待:计算 x_Ry_R 的方程是一样的,但奈何 x_P=x_Q ,我们必须使用一个不一样的方程处理斜率问题。

m=\frac{3x_P^2+a}{2y_P}

正如我们期望的那样,可以看到, m 的表达式就是下式的一阶导数

y_P=±\sqrt{x_P^3+ax_P+b}

证明这个结果的正确性就足以说明 R 属于前并且过 PR 的直线与曲线仅仅交于两点。但同样的(它的证明还是太难了),我们不直接证明这个事实,取而代之的是用实例检验: P=Q=(1,2)

m=\frac{3x_P^2+a}{2y_P}=\frac{3\cdot1^2-7}{2\cdot2}=-1

x_R=m^2-x_P-x_Q=(-1)^2-1-1=-1

y_R=y_P+m(x_R-x_P)=2+(-1)\cdot[-1-1]=4

计算结果 P+P=-R=(-1,-4) 。正确!

尽管获得答案的流程过于冗长,但我们的方程还是相当紧凑的。这得感谢魏尔斯特拉斯标准形式:没有它,这些方程就会真的又长又繁。



【标量乘法(数乘)】

除了加法,我们还可以定义另一种算符:数乘,也即

nP=P+P+......P(n个P相加)

其中n是自然数。如果你想把玩它的话,我也写了一个数乘可视化工具

写成如上形式的话, nP 的计算看上去需要 n 次加法。如果 nk 位二进制位的话,那我们的算法复杂度就是O( 2^k ),简直闹心。

然而,我们能找到更快的算法:其中一个就是倍乘相加的算法,它操作的原则用实例解释更直白。取 n=151 ,用二进制表示就是 10010111_2 。这个二进制表示可以转化为 2 的幂次依次加和。

151=1⋅2^7+0⋅2^6+0⋅2^5+1⋅2^4+0⋅2^3+1⋅2^2+1⋅2^1+1⋅2^0

=2^7+2^4+2^2+2^1+2^0

通过这种方法,我们可以这样书写原式:

151⋅P=2^7P+2^4P+2^2P+2^1P+2^0P

倍乘相加算法需要这样操作:

\bulletP

\bullet 倍乘,得到 2P

\bullet 计算 2P+P (为了得到 2^1P+2^0P

\bullet 倍乘 2P ,从而得到 2^2P

\bullet 与上面得到的序列和相加得到 2^2P+2^1P+2^0P

\bullet 倍乘,得到 2^3P

\bullet 不作任何操作

\bullet 倍乘,得到 2^4P

\bullet 与序列和相加,得到 2^4P+2^2P+2^1P+2^0P

\bullet ……

最后,我们可以仅仅通过七次倍乘和四次加和得到 151P 的值。

如果上述描绘还不够明晰,这里还有个实现该算法的Python脚本。

def bits(n):
    """
    Generates the binary digits of n, starting
    from the least significant bit.

    bits(151) -> 1, 1, 1, 0, 1, 0, 0, 1
    """
    while n:
        yield n & 1
        n >>= 1

def double_and_add(n, x):
    """
    Returns the result of n * x, computed using
    the double and add algorithm.
    """
    result = 0
    addend = x

    for bit in bits(n):
        if bit == 1:
            result += addend
        addend *= 2

    return result

如果倍乘和加和都是复杂度为 O(1) 的操作,那这个算法的复杂度就是 O(log n) (考虑比特长度的话就是 O(k) ),这就相当优秀了,比最开始的 O(n) 算法不知道高到哪里去了。


【算法】

给定 nP ,我们至少有一种多项式时间的算法(*就是文中给的那种)可以计算 Q=nP 。但是反过来呢?我们知道 QP 需要求解 n 呢?这个问题就是大名鼎鼎的对数问题。我们称它为“对数”而不是除法是因为需要与其它加密系统保持一致(这些系统中我们使用乘方而不是乘法)。

我不知晓对数问题的任何“简单”算法,但是玩转乘法可以呈现某些端倪。例如,对于曲线和点 P(0,1) ,我们可以立即验证,如果 n 是奇数, nP 就在曲线的左半平面;如果 n 是偶数, nP 在曲线的右半平面。如果我们试验更多的点,我们可能可以找到某种模式,最终引导我们写出曲线上对数计算的有效算法。

对数问题还有个变体:离散对数问题。下篇推文中我们可以看到,如果我们减小椭圆曲线的定义域,数乘还是很“简单”,但离散对数问题就变得艰难起来。这种二元对立(对偶,duality)正是椭圆曲线加密的关键钥匙。


预告:

专栏关于数学的内容到此就告一段落了,对于一个非数学系的学生,看这些东西真是难为我了,尽管是科普性质的东西,但还是常常超出我的智商范围(;´д`)ゞ

接下来我会回到我擅长的科普方向,某21世纪学科。

下一篇文章的标题我已经想好了:震惊!毛毛虫的起源竟然是祖先乱交。( ̄▽ ̄)/

感谢阅读!

欢迎关注我们的微信公众号:

编辑于 2018-03-10

文章被以下专栏收录