Hgame 2024 week4 Crypto WP

节后一直很忙抽空写个wp。

lastRSA

csharp 复制代码
from Crypto.Util.number import *
from secret import flag

def encrypt(P,k,leak0):
    round=40
    t=114514
    x= leak0+2*t if k==1 else 2*t*leak0
    enc=2024
    while(round):
        enc+=pow(x,round,P)
        round-=1
    return enc

m=bytes_to_long(flag)
p=getStrongPrime(512)
q=getStrongPrime(512)
assert len(bin(p)[2:])==512 and len(bin(q)[2:])==512
e=0x10001
leak0=p^(q>>13)
n=p*q
enc1=encrypt(n,1,leak0)
enc2=encrypt(n,0,leak0)
c=pow(m,e,n)

print(f"enc1={enc1}")
print(f"enc2={enc2}")
print(f"c={c}")
print(f"n={n}")

"""
enc1=2481998981478152169164378674194911111475668734496914731682204172873045273889232856266140236518231314247189371709204253066552650323964534117750428068488816244218804456399611481184330258906749484831445348350172666468738790766815099309565494384945826796034182837505953580660530809234341340618365003203562639721024   
enc2=2892413486487317168909532087203213279451225676278514499452279887449096190436834627119161155437012153025493797437822039637248773941097619806471091066094500182219982742574131816371999183859939231601667171386686480639682179794271743863617494759526428080527698539121555583797116049103918578087014860597240690299394   
c=87077759878060225287052106938097622158896106278756852778571684429767457761148474369973882278847307769690207029595557915248044823659812747567906459417733553420521047767697402135115530660537769991893832879721828034794560921646691417429690920199537846426396918932533649132260605985848584545112232670451169040592        
n=136159501395608246592433283541763642196295827652290287729738751327141687762873360488671062583851846628664067117347340297084457474032286451582225574885517757497232577841944028986878525656103449482492190400477852995620473233002547925192690737520592206832895895025277841872025718478827192193010765543046480481871       
"""

思路:

enc1,enc2都是关于leak0的多项式,我用的是多项式求根的方法求出来的leak0,但是我发现小鸡块师傅的更棒。

csharp 复制代码
from Crypto.Util.number import *

e=0x10001
enc1=2481998981478152169164378674194911111475668734496914731682204172873045273889232856266140236518231314247189371709204253066552650323964534117750428068488816244218804456399611481184330258906749484831445348350172666468738790766815099309565494384945826796034182837505953580660530809234341340618365003203562639721024   
enc2=2892413486487317168909532087203213279451225676278514499452279887449096190436834627119161155437012153025493797437822039637248773941097619806471091066094500182219982742574131816371999183859939231601667171386686480639682179794271743863617494759526428080527698539121555583797116049103918578087014860597240690299394   
c=87077759878060225287052106938097622158896106278756852778571684429767457761148474369973882278847307769690207029595557915248044823659812747567906459417733553420521047767697402135115530660537769991893832879721828034794560921646691417429690920199537846426396918932533649132260605985848584545112232670451169040592        
n=136159501395608246592433283541763642196295827652290287729738751327141687762873360488671062583851846628664067117347340297084457474032286451582225574885517757497232577841944028986878525656103449482492190400477852995620473233002547925192690737520592206832895895025277841872025718478827192193010765543046480481871       

#part1 get leak0
PR.<x> = PolynomialRing(Zmod(n))
f1 = -enc1+2024
for i in range(1,41):
    f1 += (x+2*114514)^i
f2 = -enc2+2024
for i in range(1,41):
    f2 += (2*114514*x)^i
def gcd(g1, g2):
    while g2:
        g1, g2 = g2, g1 % g2
    return g1.monic()
leak0 = int(-gcd(f1, f2)[0])

求出leak0后就是leak0的剪枝求解。

csharp 复制代码
from Crypto.Util.number import *

#计算p高位以及补0
gift=13168452015078389807681744077701012683188749953280204324570483361963541298704796389757190180549802771265899020301416729606658667351017116721327316272373584
N=136159501395608246592433283541763642196295827652290287729738751327141687762873360488671062583851846628664067117347340297084457474032286451582225574885517757497232577841944028986878525656103449482492190400477852995620473233002547925192690737520592206832895895025277841872025718478827192193010765543046480481871
leakbit=13
ph = bin(gift)[2:][:leakbit] + '0'*(512-leakbit)
ph = int(ph,2)
#因为已知q的第一位为1 所有未知位从leakbit+1位开始计算
print(bin(gift)[2:])
x = bin(gift)[2:][(leakbit+1):]

def fac(x,tp,tq):
    l=len(x)
    if len(x) == 0:
        return
    if tp*tq>N:
        return

    if N%(tp+1)==0:
        print("p=",tp+1)
        return
    #得到x的第一位 15 16 17
    v = x[0]
    #得到x的后几位 16 17 18...
    r = x[1:]
    #计算r去掉第一位后的长度 ,后续值位移的时候需要位移的长度
    l = len(r)
    if (tp+(1<<(l+1)))*(tq+(1<<(l+leakbit+1)))<N:
        # print(bin(tp)[:50])
        # print(bin(tq)[:50])
        # print(l)
        return
    #判断第15 16,...
    if v == '0':
        #此时p,q的第15位同为0 1
        #同为0
        fac(r, tp, tq)
        #同为1 需要加上1位移l位
        fac(r, tp+(1<<l), tq+(1<<(l+leakbit)))
    else:
        fac(r, tp+(1<<l), tq)
        fac(r, tp, tq+(1<<(l+leakbit)))
tq = 1<<511
if x[0]=='1':
    #因为已知leak0的下一位中p的bit为1
    tp = ph
else:
    #该位补1
    tp = ph+ (1<<(512-leakbit-1))
fac(x,tp,tq)

求出来p之后getflag

csharp 复制代码
import gmpy2
from Crypto.Util.number import *
p =  13167244882304693277785720567493996610066918256369682594482416913362069704726831109204371100970154866396462315730687841430922916219416627940866383413192931
q =  10340773837858169661474323029012384377394391882332560606952494899463284596209932089793576041492039641919331765221984085549386070977506894068717765568920741

e = 65537
phi = (p - 1) * (q - 1)
d = gmpy2.invert(e, phi)
m = pow(c, d, n)
print(long_to_bytes(m))

transformation

csharp 复制代码
#!/usr/bin/env python
# coding: utf-8



from Crypto.Util.number import *
from secret import Curve,gx,gy

# flag = "hgame{" + hex(gx+gy)[2:] + "}"

def ison(C, P):
    c, d, p = C
    u, v = P
    return (u**2 + v**2 - c**2 * (1 + d * u**2*v**2)) % p == 0

def add(C, P, Q):
    c, d, p = C
    u1, v1 = P
    u2, v2 = Q
    assert ison(C, P) and ison(C, Q)
    u3 = (u1 * v2 + v1 * u2) * inverse(c * (1 + d * u1 * u2 * v1 * v2), p) % p
    v3 = (v1 * v2 - u1 * u2) * inverse(c * (1 - d * u1 * u2 * v1 * v2), p) % p
    return (int(u3), int(v3))

def mul(C, P, m):
    assert ison(C, P)
    c, d, p = C
    B = bin(m)[2:]
    l = len(B)
    u, v = P
    PP = (-u, v)
    O = add(C, P, PP)
    Q = O
    if m == 0:
        return O
    elif m == 1:
        return P
    else:
        for _ in range(l-1):
            P = add(C, P, P)
        m = m - 2**(l-1)
        Q, P = P, (u, v)
        return add(C, Q, mul(C, P, m))

c, d, p = Curve

G = (gx, gy)
P = (423323064726997230640834352892499067628999846, 44150133418579337991209313731867512059107422186218072084511769232282794765835)
Q = (1033433758780986378718784935633168786654735170, 2890573833121495534597689071280547153773878148499187840022524010636852499684)
S = (875772166783241503962848015336037891993605823, 51964088188556618695192753554835667051669568193048726314346516461990381874317)
T = (612403241107575741587390996773145537915088133, 64560350111660175566171189050923672010957086249856725096266944042789987443125)
assert ison(Curve, P) and ison(Curve, Q) and ison(Curve, G)
e = 0x10001
print(f"eG = {mul(Curve, G, e)}")

# eG = (40198712137747628410430624618331426343875490261805137714686326678112749070113, 65008030741966083441937593781739493959677657609550411222052299176801418887407)

思路:

最近看到这个题目有点多,这是一道典型的板子题目。

题目给出了一道曲线

和我在sictf Round3中做的题目进阶]2024_New_Setback差不多,不过

这题的flag在G的x,y坐标上,所以解题的思路如下:

1.通过给出的四个节点求出p,c,d的值,还原出爱德华曲线。

2.将爱德华曲线分别转换成蒙哥马利曲线再到椭圆曲线。

3.然后求该曲线的阶,从而求解出远原点G,并且重新逆变换回Edcurve,得到的横坐标和纵坐标即为flag。

step1:如何通过给出的四个节点求解出爱德华曲线的参数。

我们的目标是恢复(c,d,p)。

首先,我们有曲线

如果我们知道曲线上的多个点,就可以通过下列公式隔离参数c,d

目标是使用两个点来写出p的倍数,并执行此操作两次。然后我们可以从一对点的gcd恢复p

此时,令


同样对另一点也如此然后作差会得到p的倍数:

去分母得到:

最后,我们可以采取另一种组合以及使用最大公约数得到p:

这里需要注意,我们得到的不是精确的p,而是p的倍数,但是我们可以通过分解来得到精确的p。

有了p我们再回到上面的表达式从而计算c2d:

至此我们得到了扭曲爱德华曲线上的所有参数。

此时我们需要通过e,eG以及已知的扭曲爱德华曲线求出G。

这里参考了之前小鸡块师傅的做法
EdRSA

不过需要将扭曲爱德华曲线变换成标准爱德华曲线 参考lazzzaro佬
Edwards Curves

csharp 复制代码
p = 67943764351073247630101943221474884302015437788242536572067548198498727238923
cc = 12908728488299650872377430201970332178171657588185291326485782119189255844928
d = 8779982120820562807260290996171144226614358666469579196351820160975526615300

F = GF(p)
c = F(cc).sqrt()
print(c)
csharp 复制代码
p = 67943764351073247630101943221474884302015437788242536572067548198498727238923
cc = 12908728488299650872377430201970332178171657588185291326485782119189255844928
d = 8779982120820562807260290996171144226614358666469579196351820160975526615300
c=7143899698109428282870539364581968579753042129945786627292343174759297201080
e = 0x10001
import gmpy2

def add(P, Q):
    (x1, y1) = P
    (x2, y2) = Q

    x3 = (x1*y2 + y1*x2) * gmpy2.invert(1 + d*x1*x2*y1*y2, p) % p
    y3 = (y1*y2 - a*x1*x2) * gmpy2.invert(1 - d*x1*x2*y1*y2, p) % p
    return (x3, y3)

def mul(x, P):
    Q = (0, 1)
    while x > 0:
        if x % 2 == 1:
            Q = add(Q, P)
        P = add(P, P)
        x = x >> 1
    return Q
PR.<z> = PolynomialRing(Zmod(p))
aa = 1
dd = (d*c^4)%p
J = (2*(aa+dd)*gmpy2.invert(aa-dd,p))%p
K = (4*gmpy2.invert(aa-dd,p))%p
A = ((3-J^2)*gmpy2.invert(3*K^2,p))%p
B = ((2*J^3-9*J)*gmpy2.invert(27*K^3,p))%p

for i in  PR(z^3+A*z+B).roots():
    alpha = int(i[0])
    for j in PR(z^2-(3*alpha^2+A)).roots():
        s = int(j[0])
        s = gmpy2.invert(s, p)
        if J==alpha*3*s%p:
            Alpha = alpha
            S = s

def twist_to_weier(x,y):
    #x,y转换成标准爱德华曲线值
    v = x*gmpy2.invert(c,p)%p
    w = y*gmpy2.invert(c,p)%p
    assert (aa*v^2+w^2)%p==(1+dd*v^2*w^2)%p
    #转换成蒙哥马利曲线方程上的值
    s = (1+w)*gmpy2.invert(1-w,p)%p
    t = s*gmpy2.invert(v,p)%p
    assert (K*t^2)%p==(s^3+J*s^2+s)%p
    #转换成椭圆曲线上的方程的值
    xW = (3*s+J) * gmpy2.invert(3*K, p) % p
    yW = t * gmpy2.invert(K, p) % p
    assert yW^2 % p == (xW^3+A*xW+B) % p
    return (xW,yW)
a=1
def weier_to_twist(x,y):
    #椭圆曲线转回
    xM=S*(x-Alpha)%p
    yM=S*y%p
    assert (K*yM^2)%p==(xM^3+J*xM^2+xM)%p
    xe = xM*gmpy2.invert(yM,p)%p
    ye = (xM-1)*gmpy2.invert(xM+1,p)%p
    assert (aa*xe^2+ye^2)%p==(1+dd*xe^2*ye^2)%p
    xq = xe*c%p
    yq = ye*c%p
    assert (a*xq^2+yq^2)%p==c^2*(1+d*xq^2*yq^2)%p
    return (xq,yq)
 
E = EllipticCurve(GF(p), [A, B])
order = E.order()
print(order)
eG = (40198712137747628410430624618331426343875490261805137714686326678112749070113, 65008030741966083441937593781739493959677657609550411222052299176801418887407)
eG = twist_to_weier(40198712137747628410430624618331426343875490261805137714686326678112749070113, 65008030741966083441937593781739493959677657609550411222052299176801418887407)
print(eG)
eG = E(eG)
print(gmpy2.gcd(e,order))
t = gmpy2.invert(e,order)
G = t*eG
print(G)
G = weier_to_twist(35733349967727579207362409511868045188603684677107507326049720528422212540295,6262749945313057631927156406870959025196549376410411046740120315141730009195)
print(G)
gx,gy=G
flag = "hgame{" + hex(gx+gy)[2:] + "}"
print(flag)
相关推荐
liu_chunhai10 分钟前
设计模式(3)builder
java·开发语言·设计模式
Mr.D学长15 分钟前
毕业设计 深度学习社交距离检测系统(源码+论文)
python·毕业设计·毕设
姜学迁18 分钟前
Rust-枚举
开发语言·后端·rust
wdxylb18 分钟前
解决Python使用Selenium 时遇到网页 <body> 划不动的问题
python
冷白白19 分钟前
【C++】C++对象初探及友元
c语言·开发语言·c++·算法
凌云行者23 分钟前
rust的迭代器方法——collect
开发语言·rust
代码骑士26 分钟前
【一起学NLP】Chapter3-使用神经网络解决问题
python·神经网络·自然语言处理
It'sMyGo27 分钟前
Javascript数组研究09_Array.prototype[Symbol.unscopables]
开发语言·javascript·原型模式
睡觉然后上课38 分钟前
c基础面试题
c语言·开发语言·c++·面试
qing_0406031 小时前
C++——继承
开发语言·c++·继承