题目1:
from Crypto.Util.number import *
from secret import flag
assert flag[:5]=='cnss{' and flag[-1] == '}'
flag_k = bytes_to_long(flag[5:-1].encode())
p = 1096126227998177188652856107362412783873814431647
a = 0
b = 5
E = EllipticCurve(GF(p), [a, b])
assert E.order() == p
base_point = E(626099523290649705896889901241128842906228328604,886038875771695334071307095455656761758842526929)
assert base_point in E
assert flag_k < p
Q = flag_k*base_point
print(Q)
# (240653647745552223089451307742208085297121769374 : 1041806436100548540817642210994295951394712587396 : 1)
解题思路:
- 由
assert E.order() == p
可知椭圆曲线的阶等于p
- 本题考查了ECC中的一类特殊的攻击——Smart's attack
- 当椭圆曲线的阶等于
p
时,椭圆曲线上的所有非零点可以构成一个循环群,简而言之,椭圆曲线上的所有点都是生成元;这样做既有便利之处,同时也很容易受到Smart's attack
解答:
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)
p = 1096126227998177188652856107362412783873814431647
a = 0
b = 5
E = EllipticCurve(GF(p), [a, b])
P = E(626099523290649705896889901241128842906228328604,886038875771695334071307095455656761758842526929)
Q = E(240653647745552223089451307742208085297121769374,1041806436100548540817642210994295951394712587396)
n = SmartAttack(P, Q, p)
print("cnss{" + str(bytes.fromhex(hex(n)[2:]))[2:-1] + "}")
#cnss{DLPise45y_if5pecia1}
def _lift(E, P, gf):
x, y = map(ZZ, P.xy())
for point_ in E.lift_x(x, all=True):
_, y_ = map(gf, point_.xy())
if y == y_:
return point_
def attack(G, P):
"""
Solves the discrete logarithm problem using Smart's attack.
More information: Smart N. P., "The discrete logarithm problem on elliptic
curves of trace one"
:param G: the base point
:param P: the point multiplication result
:return: l such that l * G == P
"""
E = G.curve()
gf = E.base_ring()
p = gf.order()
assert E.trace_of_frobenius() == 1, f"Curve should have trace of Frobenius =1."
E = EllipticCurve(Qp(p), [int(a) + p * ZZ.random_element(1, p) for a in
E.a_invariants()])
G = p * _lift(E, G, gf)
P = p * _lift(E, P, gf)
Gx, Gy = G.xy()
Px, Py = P.xy()
return int(gf((Px / Py) / (Gx / Gy)))
p=1096126227998177188652856107362412783873814431647
a=0
b=5
E = EllipticCurve(GF(p), [a, b])
P=E(626099523290649705896889901241128842906228328604,886038875771695334071307095455656761758842526929)
Q = E(240653647745552223089451307742208085297121769374 , 1041806436100548540817642210994295951394712587396)
print(E.order())
attack(P,Q)
#
#def _lift(E, P, gf):
x, y = map(ZZ, P.xy())
for point_ in E.lift_x(x, all=True):
_, y_ = map(gf, point_.xy())
if y == y_:
return point_
def attack(G, P):
"""
Solves the discrete logarithm problem using Smart's attack.
More information: Smart N. P., "The discrete logarithm problem on elliptic
curves of trace one"
:param G: the base point
:param P: the point multiplication result
:return: l such that l * G == P
"""
E = G.curve()
gf = E.base_ring()
p = gf.order()
assert E.trace_of_frobenius() == 1, f"Curve should have trace of Frobenius =1."
E = EllipticCurve(Qp(p), [int(a) + p * ZZ.random_element(1, p) for a in
E.a_invariants()])
G = p * _lift(E, G, gf)
P = p * _lift(E, P, gf)
Gx, Gy = G.xy()
Px, Py = P.xy()
return int(gf((Px / Py) / (Gx / Gy)))
p=1096126227998177188652856107362412783873814431647
a=0
b=5
E = EllipticCurve(GF(p), [a, b])
P=E(626099523290649705896889901241128842906228328604,886038875771695334071307095455656761758842526929)
Q = E(240653647745552223089451307742208085297121769374 , 1041806436100548540817642210994295951394712587396)
print(E.order())
attack(P,Q)
#1096126227998177188652856107362412783873814431647
#1523098569988356183378176835303573024894705969
'''
from Crypto.Util.number import *
m = 1523098569988356183378176835303573024894705969
m = long_to_bytes(m)
print(m)
#DLPise45y_if5pecia1
'''
题目2:
# sage
from secrets import flag
p = 11093300438765357787693823122068501933326829181518693650897090781749379503427651954028543076247583697669597230934286751428880673539155279232304301123931419
A = 490963434153515882934487973185142842357175523008183292296815140698999054658777820556076794490414610737654365807063916602037816955706321036900113929329671
B = 7668542654793784988436499086739239442915170287346121645884096222948338279165302213440060079141960679678526016348025029558335977042712382611197995002316466
E = EllipticCurve(GF(p), [A, B])
P = E.random_point()
Q = flag * P
print(E)
print('P:', P)
print('Q:', Q)
# Elliptic Curve defined by y^2 = x^3 + 490963434153515882934487973185142842357175523008183292296815140698999054658777820556076794490414610737654365807063916602037816955706321036900113929329671*x + 7668542654793784988436499086739239442915170287346121645884096222948338279165302213440060079141960679678526016348025029558335977042712382611197995002316466 over Finite Field of size 11093300438765357787693823122068501933326829181518693650897090781749379503427651954028543076247583697669597230934286751428880673539155279232304301123931419
# P: (5554022717099360648521077915206867958510713570728935648722513803012487951670103349974914076311463683401346041009548809409633656449393930718778345589173915 : 1266078318886560129287459416353113688542197996795961235340234481614474504159805769053978291478602425874624451558101353431723090978689270131228854203647770 : 1)
# Q: (2758577082514053081281256667519462531364634668223896872592517478354667723237248507295586566258918736939764700935831769480917509906899250634810284495146946 : 511778894973388402517121634149232729267586460552999583843974221520798491852352254441185282292648216492508999730064294835066451755699876682807265675847421 : 1)
解答:
p = 11093300438765357787693823122068501933326829181518693650897090781749379503427651954028543076247583697669597230934286751428880673539155279232304301123931419
A = 490963434153515882934487973185142842357175523008183292296815140698999054658777820556076794490414610737654365807063916602037816955706321036900113929329671
B = 7668542654793784988436499086739239442915170287346121645884096222948338279165302213440060079141960679678526016348025029558335977042712382611197995002316466
E = EllipticCurve(GF(p),[A,B])
P = E(5554022717099360648521077915206867958510713570728935648722513803012487951670103349974914076311463683401346041009548809409633656449393930718778345589173915,1266078318886560129287459416353113688542197996795961235340234481614474504159805769053978291478602425874624451558101353431723090978689270131228854203647770)
Q = E(2758577082514053081281256667519462531364634668223896872592517478354667723237248507295586566258918736939764700935831769480917509906899250634810284495146946,511778894973388402517121634149232729267586460552999583843974221520798491852352254441185282292648216492508999730064294835066451755699876682807265675847421)
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)
flag = SmartAttack(P, Q, p)
print(bytes.fromhex(hex(flag)[2:]))
#flag{OnGA2TiyDSIoVgR}