Ep(a, b)表示椭圆曲线方程y**2 = x**3 + a*x + b,在有限域Fp中,表示所有在同余意义上满足该方程的(x, y)点,例如下图:(图片来自网络)
对椭圆曲线E23(1, 1),点P(3, 10)满足y**2 = 100 = 31 = x**3 + x + 1 (mod 23),故点P(3, 10)在曲线上
椭圆曲线上两点P(x1, y1)和Q(x2, y2)的计算关系如下:
(1) -P:-P = (x1, -y1) = (x1, p-y1)
(2) P+Q:首先需要计算参数k,定义为:
当P=Q时,k = (3*x1**2+a) / (2*y1) = (3*x1**2+a) * inv((2*y1), p) (mod p)
当P!=Q时,k = (y2-y1) / (x2-x1) = (y2-y1) * inv((x2-x1), p) (mod p)
然后计算x3, y3满足
x3 = k2 - x1 - x2 (mod p)
y3 = k * (x1 - x3) - y1 (mod p)
定义为P(x1, y1) + Q(x2, y2) = R(x3, y3)
已知椭圆曲线E23(1, 1)上两点P(3, 10),Q(9, 7),求(1) -P,(2)P+Q,(3)2P
(1) -P = (3, -10) (mod 23) = (3, 13)
(2) k = (7-10) * inv((9-3), 23) (mod 23) = (-3) * 4 (mod 23) = 11
x3 = k2 - x1 - x2 (mod p) = 109 (mod 23) = 17
y3 = k * (x1 - x3) - y1 (mod p) = 89 (mod 23) = 20,P + Q = (17, 20)
(3) k = (3*3**2+1) * inv((2*10), 23) (mod 23) = 5 * 15 (mod 23) = 6
x3 = k2 - x1 - x2 (mod p) = 30 (mod 23) = 7
y3 = k * (x1 - x3) - y1 (mod p) =-34 (mod 23) = 12,2P = (7, 12)
接下来定义有限域椭圆曲线的阶。对于曲线上一点P,若存在最小的正整数n,使得nP = O(无穷远点),则称n为P的阶。例如,在曲线E23(1, 1)中,点P(3, 13)可计算的27P = (3, -13) = -P,因此28P = O,P的阶为28。所有形如kP的点构成了一个循环阿贝尔群,其阶数为29,其中生成元为P,如下图所示:(图片来自网络)
可见这些点分布是杂乱无章的,利用这一性质诞生出椭圆曲线加密的算法
考虑K = kG,其中K、G为椭圆曲线Ep(a, b)上的点,n为G的阶(即nG = O),k为小于n的整数。根据加法法则,给定k、G计算K很容易;但反过来给定K、G,计算k则非常困难。实际使用中,p与n都会相当大,因此把n个解点逐一算出来是不可能的。上述描述中,称G为基点,k为私有密钥,K为公开密钥。通信算法如下:
可以这样做的原因是:
C1 - kC2 = M + rK - krG = M + rkG - krG = M
通常将Fp上的一条椭圆曲线描述为T=(p,a,b,G,n,h)。其中p、a、b确定一条椭圆曲线;G为基点;n为点G的阶;h是椭圆曲线上所有点的个数m与n相除的商的整数部分。
已知椭圆曲线加密Ep(a,b)参数为
p = 15424654874903,a = 16546484,b = 4548674875,
G(6478678675,5636379357093),私钥为k = 546768,求公钥K(x,y)
主要功能代码部分见下:
#!/usr/bin/python
#encoding=utf-8
from gmpy2 import invert
def ECCnegative(x, y, p):
return x, p-y
def ECCadd(x1, y1, x2, y2, p, a):
if(x1==x2):
if((y1+y2)%p==0):
return -1, -1 # infinity return
elif(y1!=y2):
print ("Input Error, Please check the input!")
return -2, -2 # error input return
else:
k = ((3 * x1 * x1 + a) * invert(2 * y1, p)) % p
x3 = (k * k - x1 - x2) % p
y3 = (k * (x1 - x3) - y1) % p
return int(x3), int(y3)
else:
k = ((y2 - y1) * invert(x2 - x1, p))%p
x3 = (k * k - x1 - x2) % p
y3 = (k * (x1 - x3) - y1) % p
return int(x3), int(y3)
def ECCmul(k, x, y, p, a):
tempx, tempy = -1, -1
nowx, nowy = x, y
while(k != 0):
mark = k & 1
k = k >> 1
if(mark == 1):
if(tempx == -1):
tempx, tempy = nowx, nowy
else:
tempx, tempy = ECCadd(tempx, tempy, nowx, nowy, p, a)
nowx, nowy = ECCadd(nowx, nowy, nowx, nowy, p, a)
return tempx, tempy
结果为(13957031351290, 5520194834100)
(备注:本题为XUSTCTF2016原题,网上部分公开的代码是错误的,因为里边一个写法问题,导致and判断被当成了与运算,如下所示:
print (-1<0 & -1<0) False(代码中写法)
print (-1<0 and -1<0) True(正确写法)
在xctf平台刷题的时候请注意需要填写错误答案)