从零开始的ECC学习😭easy_ECC
主要涉及到的椭圆曲线、费马小定理到分数取余
分数取余
计算(a/b)mod p时,可将其变为((a mod p)*(1/b mod p)) mod p
根据费马小定理
x
p
−
1
m
o
d
p
=
1
x^{p-1}mod~p=1
xp−1mod p=1,可得出
(
1
/
b
)
m
o
d
p
=
b
p
−
2
m
o
d
p
(1/b) mod~p=b^{p-2}mod~p
(1/b)mod p=bp−2mod p
def mod(a,b,p):
#a/b mod p
if b<0:
b=-b
a=-a
return (a%p*pow(b,p-2,p))%p
椭圆曲线
在学习ECC加密之前首先得知道什么是椭圆曲线(这个dalao写的很详细)
可以简单理解为一条曲线(射影平面上满足威尔斯特拉斯方程所有点的集合)。简化表示为
y
2
y^2
y2=
x
3
x^3
x3+a
x
x
x+b。考虑到要将曲线变为离散的点,于是就有
y
2
y^2
y2=
x
3
x^3
x3+a
x
x
x+b (mod p)
定义椭圆曲线上的点的加法运算(椭圆曲线阿贝尔群,详细看上面链接):
P
(
x
1
,
y
1
)
+
Q
(
x
2
,
y
2
)
=
R
(
x
3
,
y
3
)
{
x
3
=
k
2
−
x
1
−
x
2
(
m
o
d
p
)
y
3
=
k
(
x
1
−
x
3
)
−
y
1
(
m
o
d
p
)
k
=
y
2
−
y
1
x
2
−
x
1
(
m
o
d
p
)
P
≠
Q
k
=
3
x
1
2
+
a
2
y
1
(
m
o
d
p
)
P
=
Q
P(x_1,y_1)+Q(x_2,y_2)=R(x_3,y_3)\left\{ \begin{aligned} x_3 & = & k^2-x_1-x_2 (mod~p) \\ y_3 & = & k(x_1-x_3)-y_1 (mod~p)\\ k & = & \frac {y_2-y_1}{x_2-x_1} (mod~p)~~~P\not=Q\\ k & = & \frac {3x_1^2+a}{2y_1} (mod~p)~~~P=Q\\ \end{aligned}\right.
P(x1,y1)+Q(x2,y2)=R(x3,y3)⎩⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎧x3y3kk====k2−x1−x2(mod p)k(x1−x3)−y1(mod p)x2−x1y2−y1(mod p) P=Q2y13x12+a(mod p) P=Q
通过这个式子不难发现计算nP是很容易实现的,即便n很大的情况下时间复杂度也不过是O(lg n)。相比之下,没有除法运算,若要求nP中的n需要花费O(n)。
因此ECC相比于RSA具有更高的安全性,但加密所花费的时间也更多。
得知ECC的基本原理后简单处理一下代码就得出了flag:
class point:
def __init__(self,x,y):
self.x=x
self.y=y
class ell:
def __init__(self,p,a,b):
self.p=p
self.a=a
self.b=b
def add(self,pA,pB):
if pA.x==pB.x and pA.y==pB.y:
k=mod((3*(pA.x*pA.x)+self.a),(2*pA.y),self.p)
else:
k=mod((pB.y-pA.y),(pB.x-pA.x),self.p)
rx=k*k-pA.x-pB.x
rx=rx%self.p
ry=k*(pA.x-rx)-pA.y
ry=ry%self.p
R = point(rx,ry)
return R
def ne(self,n,G):
s=str(bin(n)[::-1])
sumG=G
dict={}
for i in range(len(s)):
if s[i]=='1':
dict[i]=0
maxbin=i
for i in range(0,maxbin+2):
if i in dict:
dict[i]=sumG
sumG=self.add(sumG,sumG)
flag=0
for i in dict:
if flag==0:
sumG=dict[i]
flag=1
else:
sumG=self.add(sumG,dict[i])
return sumG
def mod(a,b,p):
#a/b mod p
if b<0:
b=-b
a=-a
return (a%p*pow(b,p-2,p))%p
p = 15424654874903
a = 16546484
b = 4548674875
ep = ell(p,a,b)
G = point(6478678675,5636379357093)
k = 546768
flag=ep.ne(k,G)
print(flag.x+flag.y)