Smart's attack

题目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}
posted @ 2025-03-12 00:05  sevensnight  阅读(68)  评论(0)    收藏  举报