一、椭圆曲线群的阶
在有限域上定义的椭圆曲线包含的点的数量是有限的。给出一个定义:一个群中的元素数量称为这个群的阶(order)。
一个简单的想法就是,我们尝试把0到p-1的所有整数x代入方程,然后对于每个x都找到所有满足方程的解,这样我们就找到了曲线上所有的点。当我们的p数值很大时,算法的性能通常是不能接受的。幸运的是,有一个更快的计算阶的算法:Schoof's algorithm。它能在多项式时间内运行完毕。[如下链接是Python实现Schoof算法]
二、标量乘法和循环子群
与实数一样,乘法可以定义为:
nP = P+P+...+P+P
我们称nP这样的结果为P的倍数
Fp中椭圆曲线的点乘法有一个有趣的性质。取 曲线上的点 ,P=(3,6) 。现在我们计算出所有P的点乘倍数:
在这里,我们可以立即发现:P的倍数只有5个点,椭圆曲线的其他点从未出现过。其次,它们是循环重复的。我们可以写作:
这五个方程可以被“压缩”成一个方程 kP = (k mod 5)P
不仅如此,我们还可以立即验证这五个点是否在加法下闭合。这意味着:无论对这五个点进行多少次相加,结果总是这五点之一。同样,椭圆曲线的其他点永远不会出现在结果中。
上式描述了一个简单的事实:如果我们把两个P的倍数相加,结果将是另一个P的倍数。换句话说,P的倍数在点加法下是封闭的。这就可以推导出一个重要的结论:
取椭圆曲线上任意一点P,所有P的倍数构成的集合是”定义在Fp上的椭圆曲线群“的一个循环子群。(这里有两个数学概念,子群和循环群)
“子群”首先是一个群,并且它的所有元素是另一个群的非空子集。“循环子群”是元素循环重复的子群,循环群中的每个元素都可以写成是一个基本元素的倍数,就像我们在前面的例子中展示的那样。我们把点P这样的基本元素称为循环子组的生成器或基点。
三、子群的阶(Subgroup order)
点 P为基点所产生的子群(下文用子群P代称)的阶是多少?我们不能使用上文提到的Schoof算法来计算,因为该算法只适用于整个椭圆曲线,而不适用于子群。为了解决这个问题,我们还需要更多的信息:
- 我们已经将阶定义为一个群的元素数量。这个定义仍然有效,但是在循环子组中,我们可以给出一个新的等价定义: 子群P的阶是使得 nP=0 的最小的正整数 n。
- 子群P的阶可以通过拉格朗日定理与椭圆曲线群的阶相联系,拉格朗日定理指出子群的阶是父群阶的除数。换句话说,如果椭圆曲线包含 N个点,并且它的一个子群包含 n点,那么 n是的 N 的除数。
- 这两个信息组合在一起就给我们提供了一种找出一个基点为P的子群的阶的思路:
1、使用Schoof算法计算椭圆曲线群的阶数N;
2、找到N的所有除数;
3、对每个N 的除数n ,计算nP ;
4、使 nP=0 成立的最小n就是子群P的阶
此时我们考虑一种特殊情况:假设一个椭圆曲线群的阶数N是质数,那么这个椭圆曲线的子群的阶就只有两种情况:
- 子群的阶是1,此时的子群只包含一个点0;
- 子群的阶是N,此时的子群包含椭圆曲线上的所有
四、找到基点(Finding a base point)
对于我们的ECC算法,我们需要的是高阶的子群。所以一般来说,我们会选择一条椭圆曲线,计算它的阶数N,选择一个较大的除数作为子群阶数n,最终找到一个合适的基点。也就是说:我们不会选择一个基点然后计算它的阶,相反,我们会首先选择一个看起来足够好的阶(也就是足够大),然后我们会寻找一个合适的基点。下面详细讨论这一过程:
首先,我们要再引入一个术语:余因子(cofactor)。通过前文提到的拉格朗日定理推导出群与子群的阶的关系 ℎ=N/n 一定是一个整数,这里的 ℎ 就是余因子。
我们还有一个结论:对椭圆曲线上任意一点 P有 NP=0 。原因很简单,因为N是所有子群的阶的倍数,我们用余因子的定义,可以把这个结论写作:n(hP)=0
现在假设n是一个质数,那么上面这个等式实际上就告诉我们点 G=ℎP 可以生成一个 n 阶子群(除非点 G=ℎP=0 ,这种情况下生成的子群的阶是1)
有鉴于此,我们的算法概述如下:
- 计算椭圆曲线的阶数 N
- 选择子群的阶数 n。为了使算法有效,这个数字必须是质数,并且必须是 N 的除数。
- 计算余因子ℎ=N/n
- 选择椭圆曲线上的一个随机点 P
- 计算 G=ℎP
- 若 G=0 , 就回到步骤4, 否则,我们就找到了一个子群的基点,阶数为 n 和余因子为 ℎ
请注意,此算法仅在n是质数时有效。如果 n不是质数,那么 G的阶数可能是 n 的除数之一。