ECC椭圆曲线加密.
ECC椭圆曲线加密
ECC也算是困扰已久的题型 现在通过几道题目 来初步了解一下这一类题型
有几种常见的算法下面先展开讲讲适用场景和使用方法discretelog(),smart’ sattack,Pohlig_Hellman
discrete_log()函数
discrete_log(a,base,ord,operation)
离散对数通用的算法,但不适用较大的数
参数说明:求解以base为底,a的对数;ord为base的阶,可以缺省,operation可以是+与*,默认为乘法
smart’ sattack
使用条件:模数P是质数,且E的阶(E上点的个数)等于P时可以使用
E=EllipticCurve(GF(p),[0,0,0,a,b])
E.order()=p
若输出是ture,则尝试打smart’ sattack
def SmartAttack(P,Q,p):
E = P.curve()
Eqp = EllipticCurve(Qp(p, 2), [ ZZ(t) + randint(0,p)*p for t in E.a_invariants() ])
P_Qps = Eqp.lift_x(ZZ(P.xy()[0]), all=True)
for P_Qp in P_Qps:
if GF(p)(P_Qp.xy()[1]) == P.xy()[1]:
break
Q_Qps = Eqp.lift_x(ZZ(Q.xy()[0]), all=True)
for Q_Qp in Q_Qps:
if GF(p)(Q_Qp.xy()[1]) == Q.xy()[1]:
break
p_times_P = p*P_Qp
p_times_Q = p*Q_Qp
x_P,y_P = p_times_P.xy()
x_Q,y_Q = p_times_Q.xy()
phi_P = -(x_P/y_P)
phi_Q = -(x_Q/y_Q)
k = phi_Q/phi_P
return ZZ(k)
l= SmartAttack(P, Q, p)
print(l)
Pohlig_Hellman
P是质数,且P-1包含的质因子较少&较小,如果P可被分解,即可尝试转化为CRT进行求解
factordb.com上网站试试是否可以分解
主要思想就是把一个模数转化为多组模数进行求解
def Pohlig_Hellman(n,P,Q):
factors, exponents = zip(*factor(n))
primes = [factors[i] ^ exponents[i] for i in range(len(factors))][:-1]
print(primes)
dlogs = []
for fac in primes:
t = int(int(P.order()) // int(fac))
dlog = discrete_log(t*Q,t*P,operation="+")
dlogs += [dlog]
print("factor: "+str(fac)+", Discrete Log: "+str(dlog)) #calculates discrete logarithm for each prime order
l = crt(dlogs,primes)
return l
l = Pohlig_Hellman(n,P,Q)
print(l)
看看最经典的一题
[第五空间 2021]ecc
print 'Try to solve the 3 ECC'
from secret import flag
from Crypto.Util.number import *
assert(flag[:5]=='flag{')
flag = flag[5:-1]
num1 = bytes_to_long(flag[:7])
num2 = bytes_to_long(flag[7:14])
num3 = bytes_to_long(flag[14:])
def ECC1(num):
p = 146808027458411567
A = 46056180
B = 2316783294673
E = EllipticCurve(GF(p),[A,B])
P = E.random_point()
Q = num*P
print E
print 'P:',P
print 'Q:',Q
def ECC2(num):
p = 1256438680873352167711863680253958927079458741172412327087203
#import random
#A = random.randrange(389718923781273978681723687163812)
#B = random.randrange(816378675675716537126387613131232121431231)
A = 377999945830334462584412960368612
B = 604811648267717218711247799143415167229480
E = EllipticCurve(GF(p),[A,B])
P = E.random_point()
Q = num*P
print E
print 'P:',P
print 'Q:',Q
factors, exponents = zip(*factor(E.order()))
primes = [factors[i] ^ exponents[i] for i in range(len(factors))][:-1]
print primes
dlogs = []
for fac in primes:
t = int(int(P.order()) / int(fac))
dlog = discrete_log(t*Q,t*P,operation="+")
dlogs += [dlog]
print("factor: "+str(fac)+", Discrete Log: "+str(dlog)) #calculates discrete logarithm for each prime order
print num
print crt(dlogs,primes)
def ECC3(num):
p = 0xd3ceec4c84af8fa5f3e9af91e00cabacaaaecec3da619400e29a25abececfdc9bd678e2708a58acb1bd15370acc39c596807dab6229dca11fd3a217510258d1b
A = 0x95fc77eb3119991a0022168c83eee7178e6c3eeaf75e0fdf1853b8ef4cb97a9058c271ee193b8b27938a07052f918c35eccb027b0b168b4e2566b247b91dc07
B = 0x926b0e42376d112ca971569a8d3b3eda12172dfb4929aea13da7f10fb81f3b96bf1e28b4a396a1fcf38d80b463582e45d06a548e0dc0d567fc668bd119c346b2
E = EllipticCurve(GF(p),[A,B])
P = E.random_point()
Q = num*P
print E
print 'P:',P
print 'Q:',Q
ECC1(num1)
print '=============='
ECC2(num2)
print '=============='
ECC3(num3)
题目分为三块 对应着这ecc的三种不同的类型 同时也是三种不同的解法
首先先来学习第一块
输出的数据为
Elliptic Curve defined by y^2 = x^3 + 46056180*x + 2316783294673 over Finite Field of size 146808027458411567
P: (119851377153561800 : 50725039619018388 : 1)
Q: (22306318711744209 : 111808951703508717 : 1)
数比较小,可以直接使用_discretelog()求出
from Crypto.Util.number import *
p = 146808027458411567
a = 46056180
b = 2316783294673
E = EllipticCurve(GF(p),(a,b))
P = E(119851377153561800,50725039619018388)
Q = E(22306318711744209,111808951703508717)
num1 = discrete_log(Q,P,operation = '+')
print(long_to_bytes(num1))
#13566003730592612
#b'025ab3d'
接下来是第二块
输出的数据为
Elliptic Curve defined by y^2 = x^3 + 377999945830334462584412960368612*x + 604811648267717218711247799143415167229480 over Finite Field of size 1256438680873352167711863680253958927079458741172412327087203
P: (550637390822762334900354060650869238926454800955557622817950 : 700751312208881169841494663466728684704743091638451132521079 : 1)
Q: (1152079922659509908913443110457333432642379532625238229329830 : 819973744403969324837069647827669815566569448190043645544592 : 1)
题目中提示了使用Pohlig_Hellman算法解密
p = 1256438680873352167711863680253958927079458741172412327087203
a = 377999945830334462584412960368612
b = 604811648267717218711247799143415167229480
E = EllipticCurve(GF(p),[a,b])
P = E(550637390822762334900354060650869238926454800955557622817950,700751312208881169841494663466728684704743091638451132521079)
Q = E(1152079922659509908913443110457333432642379532625238229329830,819973744403969324837069647827669815566569448190043645544592)
# Q = k * P
n = E.order()
def Pohlig_Hellman(n,P,Q):
factors, exponents = zip(*factor(n))
primes = [factors[i] ^ exponents[i] for i in range(len(factors))][:-1]
print(primes)
dlogs = []
for fac in primes:
t = int(int(P.order()) // int(fac))
dlog = discrete_log(t*Q,t*P,operation="+")
dlogs += [dlog]
print("factor: "+str(fac)+", Discrete Log: "+str(dlog)) #calculates discrete logarithm for each prime order
num2 = crt(dlogs,primes)
return num2
num2 = Pohlig_Hellman(n,P,Q)
print(num2)
'''
[2, 27, 5, 7, 212117, 302426983]
factor: 2, Discrete Log: 1
factor: 27, Discrete Log: 10
factor: 5, Discrete Log: 4
factor: 7, Discrete Log: 6
factor: 212117, Discrete Log: 126450
factor: 302426983, Discrete Log: 211578426
b'9-2521-'
'''
最后是第三块
输出内容如下
Elliptic Curve defined by y^2 = x^3 + 490963434153515882934487973185142842357175523008183292296815140698999054658777820556076794490414610737654365807063916602037816955706321036900113929329671*x + 7668542654793784988436499086739239442915170287346121645884096222948338279165302213440060079141960679678526016348025029558335977042712382611197995002316466 over Finite Field of size 11093300438765357787693823122068501933326829181518693650897090781749379503427651954028543076247583697669597230934286751428880673539155279232304301123931419
P: (10121571443191913072732572831490534620810835306892634555532657696255506898960536955568544782337611042739846570602400973952350443413585203452769205144937861 : 8425218582467077730409837945083571362745388328043930511865174847436798990397124804357982565055918658197831123970115905304092351218676660067914209199149610 : 1)
Q: (964864009142237137341389653756165935542611153576641370639729304570649749004810980672415306977194223081235401355646820597987366171212332294914445469010927 : 5162185780511783278449342529269970453734248460302908455520831950343371147566682530583160574217543701164101226640565768860451999819324219344705421407572537 : 1)
可以发现椭圆曲线阶数与p相等,用_smart’ sattack可以求出_
p = 0xd3ceec4c84af8fa5f3e9af91e00cabacaaaecec3da619400e29a25abececfdc9bd678e2708a58acb1bd15370acc39c596807dab6229dca11fd3a217510258d1b
A = 0x95fc77eb3119991a0022168c83eee7178e6c3eeaf75e0fdf1853b8ef4cb97a9058c271ee193b8b27938a07052f918c35eccb027b0b168b4e2566b247b91dc07
B = 0x926b0e42376d112ca971569a8d3b3eda12172dfb4929aea13da7f10fb81f3b96bf1e28b4a396a1fcf38d80b463582e45d06a548e0dc0d567fc668bd119c346b2
E = EllipticCurve(GF(p),[A,B])
P = E(10121571443191913072732572831490534620810835306892634555532657696255506898960536955568544782337611042739846570602400973952350443413585203452769205144937861,8425218582467077730409837945083571362745388328043930511865174847436798990397124804357982565055918658197831123970115905304092351218676660067914209199149610)
Q = E(964864009142237137341389653756165935542611153576641370639729304570649749004810980672415306977194223081235401355646820597987366171212332294914445469010927,5162185780511783278449342529269970453734248460302908455520831950343371147566682530583160574217543701164101226640565768860451999819324219344705421407572537)
def SmartAttack(P,Q,p):
E = P.curve()
Eqp = EllipticCurve(Qp(p, 2), [ ZZ(t) + randint(0,p)*p for t in E.a_invariants() ])
P_Qps = Eqp.lift_x(ZZ(P.xy()[0]), all=True)
for P_Qp in P_Qps:
if GF(p)(P_Qp.xy()[1]) == P.xy()[1]:
break
Q_Qps = Eqp.lift_x(ZZ(Q.xy()[0]), all=True)
for Q_Qp in Q_Qps:
if GF(p)(Q_Qp.xy()[1]) == Q.xy()[1]:
break
p_times_P = p*P_Qp
p_times_Q = p*Q_Qp
x_P,y_P = p_times_P.xy()
x_Q,y_Q = p_times_Q.xy()
phi_P = -(x_P/y_P)
phi_Q = -(x_Q/y_Q)
k = phi_Q/phi_P
return ZZ(k)
num3 = SmartAttack(P, Q, p)
print(num3)
"""
19597596255129283097357413993866074145935170485891892
b'4a81-9957-8c3381622434'
"""
拼接到得出答案NSSCTF{025ab3d9-2521-4a81-9957-8c3381622434}
[2023愚人杯]ecc_mini
from Crypto.Util.number import *
from secret import flag
flag=bytes_to_long(flag)
a =getPrime(256)
b =getPrime(256)
p =getPrime(256)
m1=int(str(flag)[:5])-4585
m2=int(str(flag)[5:])
#EllipticCurve([a1, a2, a3, a4, a6]) -- y^2+(a1)xy+(a3)y=x^3+(a2)x^2+(a4)x+(a6)
E = EllipticCurve(GF(p), [a, b])
X=E.lift_x(m1)
Y=7*X
m = E.random_point()
G = E.random_point()
k = getPrime(256)
K = k * G
r = getPrime(256)
c1 = m + r * K
c2 = r * G
w2=m[0]*m2
print(f"p = {p}")
print(f"a = {a}")
print(f"b = {b}")
print(f"k = {k}")
print(f"E = {E}")
print(f'Y = {Y}')
print(f"c1 = {c1}")
print(f"c2 = {c2}")
print(f"w2 = {w2}")
'''
p = 71397796933602469825964946338224836258949974632540581233301840806613437378503
a = 106105288190268015217241182934677375171023341761047638573248022053052499733117
b = 76170541771321874396004434442157725545076211607587599314450304327736999807927
k = 58155941823118858940343657716409231510854647214870891375273032214774400828217
E = Elliptic Curve defined by y^2 = x^3 + 34707491256665545391276236596452538912073367128507057339946181246439062354614*x + 4772744837719404570039488103932889286126236975047018081148463521123562429424 over Finite Field of size 71397796933602469825964946338224836258949974632540581233301840806613437378503
Y = (33237936857741483513705672980652927705102229733798436323453609986072499230366 : 52619411226266177137991318059937693955038910547834999771526408984808553907338 : 1)
c1 = (37414446283406201193977113266234367761786780230360175925999700345196415953455 : 17037724145039910971426670298726906655653040365428438334942732090559637519851 : 1)
c2 = (60560423732267272277570046154733119097475794979191838027420415113112056962844 : 54372226143125971429691267751299496959531971082475860532181772357190222938465 : 1)
w2 = 16315249811700998894876359855091105114973337718373913477026230968747515636405
'''
可以看到已经有部分的明文泄露了,所以其实我们可以对前面5个数位进行爆破,但是这里有两种爆破方式,一种是直接爆破解密,将合理的值输出,另一种是根据原文代码进行爆破,先找到正确的m1,再进行解密。
p = 71397796933602469825964946338224836258949974632540581233301840806613437378503
a = 106105288190268015217241182934677375171023341761047638573248022053052499733117
b = 76170541771321874396004434442157725545076211607587599314450304327736999807927
k = 58155941823118858940343657716409231510854647214870891375273032214774400828217
from Crypto.Util.number import *
E = EllipticCurve(GF(p), [a, b])
c1 = E(37414446283406201193977113266234367761786780230360175925999700345196415953455 , 17037724145039910971426670298726906655653040365428438334942732090559637519851)
c2 = E(60560423732267272277570046154733119097475794979191838027420415113112056962844 , 54372226143125971429691267751299496959531971082475860532181772357190222938465)
print(c1 - k * c2)
#m = (71304669061767049972885792894615651818794274529315856194992266286323237158881 : 10126770036343069593803252437914418057336213410278953515516757017939543175878 : 1)
获得m2
m0 = R(71304669061767049972885792894615651818794274529315856194992266286323237158881)
w2 = R(16315249811700998894876359855091105114973337718373913477026230968747515636405)
p = 71397796933602469825964946338224836258949974632540581233301840806613437378503
R = GF(p)
from Crypto.Util.number import *
E = EllipticCurve(GF(p), [a, b])
print(w2 // m0)
#m2 = 7196365442241205186856420688221367789171469258517476477
爆破m1
import libnum
m2 = int(7196365442241205186856420688221367789171469258517476477)
for i in range(10000,100000):
m = m2 + i * 10 ** len(str(m2))
try:
flag = libnum.n2s(int(m)).decode()#可以用于滤除含不可见字符的字符串
if '{' in flag: #保证flag形式合理
print(flag)
except:
pass
#ctfshow{the_answer_is_it}
接下来就是pctf的题目了
好曲线
import hashlib
import os
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
p=12506217790875063466368723611056175369923
A=12506217790875063466368723611052784275139
B=12506217790875063466368723533070038257347
F = FiniteField(p)
E = EllipticCurve(F,[A,B])
xP=7493372729181057645036574086903590138065
yP=359098907392057890604329721532958479621
P=[xP,yP]
P = E.point(P)
Q=k*P
Q = E.point(Q)
Q=[xQ,yQ]
#xQ=9505420031620208163682758801913524369821
#yQ=5460936589331844194485299189975059431657
key=hashlib.sha256(str(k).encode()).hexdigest()
key=bytes.fromhex(key)
iv=os.urandom(16)
cipher=AES.new(key[:16],AES.MODE_CBC,iv)
c=cipher.encrypt(pad(flag.encode(),AES.block_size))
print(iv)
print(c)
#b'f\xd0\x1e\xc7[P\x19\x07E\xe0[M;\x0f\xbc@'
#b'\x9b\x1b\xc1\x08\x18\x94\x90A\xad\xbd\x18U\x923Hy\xea\xfe~\x82\xb9\xa6}R\x0c\x19.-Ru\x11\x8d\x03\x9a\x97N\xb8:\xc5\x12\xc9\x95/\x88\xfa\x08\xb6\r'
同样这道题目前半部分打smart’ sattack 先得出k的值
p=12506217790875063466368723611056175369923
A=12506217790875063466368723611052784275139
B=12506217790875063466368723533070038257347
E = EllipticCurve(GF(p),[A,B])
xP=7493372729181057645036574086903590138065
yP=359098907392057890604329721532958479621
P=[xP,yP]
P = E.point(P)
xQ=9505420031620208163682758801913524369821
yQ=5460936589331844194485299189975059431657
Q=[xQ,yQ]
Q = E.point(Q)
def SmartAttack(P,Q,p):
E = P.curve()
Eqp = EllipticCurve(Qp(p, 2), [ ZZ(t) + randint(0,p)*p for t in E.a_invariants() ])
P_Qps = Eqp.lift_x(ZZ(P.xy()[0]), all=True)
for P_Qp in P_Qps:
if GF(p)(P_Qp.xy()[1]) == P.xy()[1]:
break
Q_Qps = Eqp.lift_x(ZZ(Q.xy()[0]), all=True)
for Q_Qp in Q_Qps:
if GF(p)(Q_Qp.xy()[1]) == Q.xy()[1]:
break
p_times_P = p*P_Qp
p_times_Q = p*Q_Qp
x_P,y_P = p_times_P.xy()
x_Q,y_Q = p_times_Q.xy()
phi_P = -(x_P/y_P)
phi_Q = -(x_Q/y_Q)
k = phi_Q/phi_P
return ZZ(k)
k = SmartAttack(P, Q, p)
print(k)
#11063983210789056064816501731025997778953
解出后就是AES CBC加密
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import hashlib
import os
k = 11063983210789056064816501731025997778953
iv = b'f\xd0\x1e\xc7[P\x19\x07E\xe0[M;\x0f\xbc@'
ciphertext = b'\x9b\x1b\xc1\x08\x18\x94\x90A\xad\xbd\x18U\x923Hy\xea\xfe~\x82\xb9\xa6}R\x0c\x19.-Ru\x11\x8d\x03\x9a\x97N\xb8:\xc5\x12\xc9\x95/\x88\xfa\x08\xb6\r'
key = hashlib.sha256(str(k).encode()).digest()[:16]
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted_data = cipher.decrypt(ciphertext)
flag = unpad(decrypted_data, AES.block_size).decode('utf-8')
print("Decrypted flag:", flag)
然后是 ISCTF的题目
沉迷数学的小蓝鲨
# y² = x³ + 3x + 27 (mod p)
#
# Q(0xa61ae2f42348f8b84e4b8271ee8ce3f19d7760330ef6a5f6ec992430dccdc167, 0x8a3ceb15b94ee7c6ce435147f31ca8028d1dd07a986711966980f7de20490080)
#
# k= ?
#
# 最终flag请将解出k值的16进制转换为32位md5以ISCTF{}包裹提交
题目什么条件都没有 看着一头雾水
看看提示
HINT1
你验证过基点 G 真的在曲线上吗?(这只是个ez题,别想太复杂)
HINT2
G是这条曲线上的冒牌货,但代数运算不在乎,因为计算机可不是数学家
换句话说:题目给的点 G 虽然不满足曲线方程,但他们依旧用标准的椭圆曲线加法公式(带参数a=3)反复加倍,得到了Q=kG。
你不能直接用 Sage 的 EllipticCurve 构造这两个点(它会校验曲线方程),但你可以自己实现椭圆曲线的加法/倍乘,在程序中绕过合
性检查,直接用 BSGS 找出 k
这里引入了BSGS算法,先介绍一下 BSGS(baby-step giant-step),即大步小步算法。常用于求解离散对数问题
再然后可以看到题目少了条件 题目要求k值 所以点G理应是已知的 提示区块链常用参数 即可想到secp256k1 椭圆曲线的 生成元(Generator / Base Point)
开始解题
python
p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
a = 3
G = (
0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,
0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
)
Q = (
0xa61ae2f42348f8b84e4b8271ee8ce3f19d7760330ef6a5f6ec992430dccdc167,
0x8a3ceb15b94ee7c6ce435147f31ca8028d1dd07a986711966980f7de20490080
)
O = None
def inv_mod(x):
return pow(x % p, p - 2, p)
def point_add(P, Q):
if P is None:
return Q
if Q is None:
return P
x1, y1 = P
x2, y2 = Q
if x1 == x2 and (y1 + y2) % p == 0:
return None
if x1 == x2 and y1 == y2:
if y1 == 0:
return None
lam = (3 * x1 * x1 + a) * inv_mod(2 * y1) % p
else:
lam = (y2 - y1) * inv_mod(x2 - x1) % p
x3 = (lam * lam - x1 - x2) % p
y3 = (lam * (x1 - x3) - y1) % p
return (x3, y3)
def scalar_mul(P, k):
R = None
T = P
while k:
if k & 1:
R = point_add(R, T)
T = point_add(T, T)
k >>= 1
return R
# Baby-step Giant-step
import math
m = 1 << 16
baby = {}
R = None
for j in range(m):
baby[R] = j
R = point_add(R, G)
mG = scalar_mul(G, m)
neg_mG = (mG[0], (-mG[1]) % p)
gamma = Q
for i in range(m + 1):
if gamma in baby:
k = i * m + baby[gamma]
print("找到 k =", k)
break
gamma = point_add(gamma, neg_mG)
要点说明:
point_add 和 scalar_mul 没有检查点是否在曲线上,使用相同的 a=3参数,复现题目里的 “代数运算”。
BSGS 中要减去 mG
m 的步长可以调大(比如改为 1 << 17),如果第一次没找到再扩大就好
babyECC2
from secret import flag
import random
bits = 64
p = random_prime(2^bits)
a = randint(1, bits)
b = randint(1, bits)
E = EllipticCurve(GF(p), [a, b])
g = E.random_element()
x = random_prime(2^16)
pk = x*g
k = randint(1, p-1)
kPoint = k*pk
kp = kPoint.xy()
c = []
for i in range(len(flag)):
c.append( (ord(flag[i]) ^^ int(kp[i%2])) & 0xff )
c = bytes(c).hex()
print(p)
print(a)
print(b)
print(g)
#print(g.order())
print(c)
4698491801183562589
58
59
(2965797230620625775 : 4310564666276679314 : 1)
ac73a774a25bd512d543dc468542c9428141800dd041d043c918d112850dd515d6128214d1138211d71599
读题 一个正常的椭圆曲线 随机取点得到了g,pk 最终得到kp(某个点)
然后再看循环 将flag中的每一个字符转化ASC值再同kp异或(i为奇数则同x,为偶数则同y)
&0xff确保结果保持在 0–255(一个字节),通常用于防止溢出
最后转化为16进制
但是输出少了很多东西 没办法正着推出kp的两个值 因为题目是HSCTF 所以通过c先反推出x,y 随后即可正常求解
c = 'ac73a774a25bd512d543dc468542c9428141800dd041d043c918d112850dd515d6128214d1138211d71599'
c = bytes.fromhex(c)
key = [c[0]^ord('H'), c[1]^ord('S')]
print(key)
flag = ''
for i in range(len(c)):
flag += chr(c[i] ^ key[i%2])
print(flag)

浙公网安备 33010602011771号