Twisted Hessian曲线

题目:

from Crypto.Util.number import *
from secret import flag

def add_THcurve(P, Q):
    if P == (0, 0):
        return Q
    if Q == (0, 0):
        return P
    x1, y1 = P
    x2, y2 = Q
    x3 = (x1 - y1 ** 2 * x2 * y2) * pow(a * x1 * y1 * x2 ** 2 - y2, -1, p) % p
    y3 = (y1 * y2 ** 2 - a * x1 ** 2 * x2) * pow(a * x1 * y1 * x2 ** 2 - y2, -1, p) % p
    return x3, y3

def mul_THcurve(n, P):
    R = (0, 0)
    while n > 0:
        if n % 2 == 1:
            R = add_THcurve(R, P)
        P = add_THcurve(P, P)
        n = n // 2
    return R

p = 10297529403524403127640670200603184608844065065952536889
a = 2
G = (8879931045098533901543131944615620692971716807984752065, 4106024239449946134453673742202491320614591684229547464)

FLAG = flag.lstrip(b'DASCTF{').rstrip(b'}')
assert len(FLAG) == 15
m = bytes_to_long(FLAG)
assert m < p
Q = mul_THcurve(m, G)
print("Q =", Q)
# Q = (6784278627340957151283066249316785477882888190582875173, 6078603759966354224428976716568980670702790051879661797)

解题思路:

方法1:

  1. 定义椭圆曲线和点:
    • p是一个大素数,定义了有限域Fp
    • a是一个常数
    • PQ是椭圆曲线上的点,表示为(x,y)坐标
    • d是通过给定公式计算得到的一个常数
  2. 构造三次曲线:
    • 使用R.<x,y,z> = Zmod(p)[]定义了一个多项式环
    • cubic = 2 * x^3 + y^3 + z^3 - d*x*y*z定义了一个三次曲线
    • E = EllipticCurve_from_cubic(cubic,morphism=True)将三次曲线转换为椭圆曲线
  3. 点的转换:
    • P = E(P)Q = E(Q)将给定的点转换为椭圆曲线上的点
  4. 计算点的阶:
    • P_ord = P.order()计算点P的阶,即最小的正整数n使得nP=O(椭圆曲线的无穷远点)
  5. Pohlig-Hellman算法:
    • Pohlig_Hellman(n,P,Q)函数实现了Pohlig-Hellman算法,用于求解离散对数问题
    • 算法首先将P的阶n分解为质因数
    • 对于每个质因数fac,计算t=facP.order()
    • 计算tQtP,然后求解离散对数dlog=discretelog(t∗Q,t∗P,operation="+")
    • 使用中国剩余定理crt(dlogs, primes)合并所有离散对数的结果
  6. 输出结果:
    • num2 = Pohlig_Hellman(P_ord, P, Q)调用Pohlig-Hellman算法求解离散对数

方法2(不推荐):

  • 因为阶倍数相差过大计算效率太低,比较适用于下题(HGAME-week2-TH曲线)

方法3:

  • 方法1不同的是,方法1使用了Pohlig-Hellman算法CRT来求解离散对数;这个方法3直接使用了SageMath的discrete_log函数来求解离散对数
  • 不过两个方法的思路差不多,都使用了将问题简化到更小子群的思想,前两个方法通过Pohlig-Hellman算法将问题分解为多个小问题,然后使用CRT合并结果;这个方法通过乘以一个随机整数<font style="color:rgb(6, 6, 7);">r</font>将点<font style="color:rgb(6, 6, 7);">G</font><font style="color:rgb(6, 6, 7);">Q</font>缩小到一个更小的子群中,然后直接求解离散对数

解答:

法1:
p = 10297529403524403127640670200603184608844065065952536889
a = 2
P = (8879931045098533901543131944615620692971716807984752065, 4106024239449946134453673742202491320614591684229547464)
Q = (6784278627340957151283066249316785477882888190582875173, 6078603759966354224428976716568980670702790051879661797)
d = (a * Q[0] ** 3 + Q[1] ** 3 + 1) * inverse_mod(Q[0] * Q[1], p) % p

# construct ECC to get a solution of 2X^3+Y^3+Z^3=dXYZ
R.<x,y,z> = Zmod(p)[]
cubic = 2 * x^3 + y^3 + z^3 - d*x*y*z
E = EllipticCurve_from_cubic(cubic,morphism=True)
P = E(P)
Q = E(Q)
P_ord = P.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(P_ord,P,Q)
print(hex(num2))
print(bytes.fromhex(hex(num2)[2:]))
'''
[9, 49, 11, 19, 29, 1361, 6421, 3376343, 1815576031, 295369272787]
factor: 9, Discrete Log: 3
factor: 49, Discrete Log: 0
factor: 11, Discrete Log: 0
factor: 19, Discrete Log: 7
factor: 29, Discrete Log: 8
factor: 1361, Discrete Log: 225
factor: 6421, Discrete Log: 3560
factor: 3376343, Discrete Log: 837823
factor: 1815576031, Discrete Log: 1495286767
factor: 295369272787, Discrete Log: 292393302300
'''
#0x654073795f637552764c5f63306f21
#e@sy_cuRvL_c0o!
from sage.all import *

p = 10297529403524403127640670200603184608844065065952536889
a = 2
G = (8879931045098533901543131944615620692971716807984752065, 4106024239449946134453673742202491320614591684229547464)
Q = (6784278627340957151283066249316785477882888190582875173, 6078603759966354224428976716568980670702790051879661797)

d = ZZ((a*G[0]**3 + G[1]**3 + 1) * inverse_mod(G[0]*G[1], p) % p)

F = GF(p)
x, y, z = QQ["x,y,z"].gens()
eq = a*x ** 3 + y ** 3 + z ** 3 - d * x * y * z
phi = EllipticCurve_from_cubic(eq)
E = phi.codomain().change_ring(F)

fx, fy, fz = map(lambda f: f.change_ring(F), phi.defining_polynomials())
phiP = lambda x, y, z=1: E(fx(x, y, z) / fz(x, y, z), fy(x, y, z) / fz(x, y, z))
EG = phiP(G[0], G[1], 1)
EQ = phiP(Q[0], Q[1], 1)

order = EG.order()
subs = list(factor(order))
sks = list()
mods = list()
print(order, factor(order))
for sub, i in subs[:-1]:
    sub = sub**i
    A = order//sub * EG
    B = order//sub * EQ
    sk = discrete_log_lambda(B, A, (0, sub), operation="+")
    sks.append(sk)
    mods.append(sub)
    print(sub, sk)
sk = crt(sks, mods)
#sk = 126879961154507942934597133279713552400602

print(sk.nbits(), sk)
print(hex(int(sk)))
print(bytes.fromhex(hex(sk)[2:]))
'''
2574382350881100781910167550168543979059426145711434631 3^2 * 7^2 * 11 * 19 * 29 * 1361 * 6421 * 3376343 * 1815576031 * 295369272787 * 60869967041981
9 3
49 49
11 11
19 7
29 8
1361 225
6421 3560
3376343 837823
1815576031 1495286767
295369272787 292393302300
119 525729205728344257526560548008783649
'''
#0x654073795f637552764c5f63306f21
#e@sy_cuRvL_c0o!
法2:

都是因为阶相差过大计算效率太低(不推荐下面做法)

p = 10297529403524403127640670200603184608844065065952536889
a = 2
G = (8879931045098533901543131944615620692971716807984752065, 4106024239449946134453673742202491320614591684229547464)
d = (a*G[0]^3+G[1]^3+1)*inverse_mod(G[1]*G[0], p)%p
Q = (6784278627340957151283066249316785477882888190582875173, 6078603759966354224428976716568980670702790051879661797)

def calculate_coefficients(a, d):
    d_3 = d*inverse_mod(3, p)%p             # d / 3
    tmp = a - d_3**3                    # a - d^3/27
    a0 = 1
    a1 = (-3 * d_3 * inverse_mod(tmp, p))%p
    a3 = (-9 * inverse_mod(tmp**2, p)) % p
    a2 = (-9 * d_3**2 * inverse_mod(tmp**2, p))%p
    a4 = (-27 * d_3 * inverse_mod(tmp**3, p))%p
    a6 = (-27 * inverse_mod(tmp**4, p))%p
    
    return [a1, a2, a3, a4, a6]

aa = calculate_coefficients(a, d)
E = EllipticCurve(GF(p), aa)
def Herssian_to_Weierstrass(Point):
    x, y = Point
    u = ((-3 * inverse_mod((a - d^3*inverse_mod(27, p)), p)*x * inverse_mod(d*x*inverse_mod(3,p) - (-y) + 1, p))) % p
    v = ((-9 * inverse_mod((a - d^3*inverse_mod(27, p))^2, p) ) * (-y) * inverse_mod(d*x*inverse_mod(3,p) - (-y) + 1, p))%p
    return (u, v)

G = E(Herssian_to_Weierstrass(G))
Q = E(Herssian_to_Weierstrass(Q))
m = discrete_log(Q, G, operation='+')
print(hex(m))
#0x654073795f637552764c5f63306f21
#e@sy_cuRvL_c0o!
from sage.all import *

# 定义参数
p = 10297529403524403127640670200603184608844065065952536889
a = 2
G = (8879931045098533901543131944615620692971716807984752065, 4106024239449946134453673742202491320614591684229547464)
Q = (6784278627340957151283066249316785477882888190582875173, 6078603759966354224428976716568980670702790051879661797)

# 计算 d
G0, G1 = G
d = (a * G0^3 + G1^3 + 1) * inverse_mod(G0 * G1, p) % p

# 定义椭圆曲线
R = Zmod(p)['x, y, z']; (x, y, z) = R._first_ngens(3)
cubic = a * x^3 + y^3 + z^3 - d * x * y * z
E = EllipticCurve_from_cubic(cubic, morphism=True)

# 将点 G 和 Q 映射到椭圆曲线上
G = E(G)
Q = E(Q)

# 检查点的阶
order_G = G.order()
order_Q = Q.order()
#2574382350881100781910167550168543979059426145711434631
#1592073191639518108787982405793781063116528228640343
#Q的阶能整除G的阶,结果为1617(太大)

# 验证 Q 的阶是否能整除 G 的阶
if order_Q.divides(order_G):
    print("Q 的阶能整除 G 的阶,离散对数问题可能有解。")
    x = discrete_log(Q, G, operation='+')
    print("离散对数结果:", x)
else:
    print("Q 的阶不能整除 G 的阶,离散对数问题无解。")
'''
Q 的阶能整除 G 的阶,离散对数问题可能有解。
离散对数结果: 525729205728344257526560548008783649
'''
#e@sy_cuRvL_c0o!
法3:
p = 10297529403524403127640670200603184608844065065952536889
a = 2
G = (8879931045098533901543131944615620692971716807984752065, 4106024239449946134453673742202491320614591684229547464)
Q = (6784278627340957151283066249316785477882888190582875173, 6078603759966354224428976716568980670702790051879661797)

d = (a*G[0]^3 + G[1]^3 + 1) * inverse_mod(G[0]*G[1], p) % p

R.<x,y,z> = Zmod(p)[]
cubic = a*x^3 + y^3 + z^3 - d*x*y*z
E = EllipticCurve_from_cubic(cubic,morphism=True)
G = E(G)
Q = E(Q)
r = 60869967041981
m = discrete_log(r*Q, r*G, operation='+')
print(hex(m))
print(bytes.fromhex(hex(m)[2:]))
#0x654073795f637552764c5f63306f21
#e@sy_cuRvL_c0o!
posted @ 2025-03-12 00:05  sevensnight  阅读(40)  评论(0)    收藏  举报