DASCTF-Apr-2023-X-SU战队2023开局之战-Crypto

  1. easySign
  2. ECC

拖了好久了

easySign

from secret import r, t
from Crypto.Util.number import *

flag = b'xxx'
flag = bytes_to_long(flag)
e = 0x10001

def gen_keys():
    p = getPrime(1024)
    q = getPrime(1024)
    phi = (p-1)*(q-1)
    d = inverse(e,phi)
    n = p*q
    print(f'n = {n}')
    WHATF = (d ** 3 + 3) % phi
    print(f'WHATF= {WHATF}')
    return d, n, WHATF

def easy_sign(n,d):
    m = flag * pow(r,e**2+d**2,n) % n
    s = pow(m,d,n)
    return s

def gift():
    assert t > 0
    gift = pow(r,t) - 1
    #print(t)
    print(isPrime(gift))

d,n,WHATF = gen_keys()
gift()
sign = easy_sign(n,d)
print(f'sign = {sign}')

# n = 17501785470905115084530641937586010443633001681612179692218171935474388105810758340844015368385708349722992595891293984847291588862799310921139505076364559140770828784719022502905431468825797666445114531707625227170492272392144861677408547696040355055483067831733807927267488677560035243230884564063878855983123740667214237638766779250729115967995715398679183680360515620300448887396447013941026492557540060990171678742387611013736894406804530109193638867704765955683067309269778890269186100476308998155078252336943147988308936856121869803970807195714727873626949774272831321358988667427984601788595656519292763705699
# WHATF= 7550872408895903340469549867088737779221735042983487867888690747510707575208917229455135563614675077641314504029666714424242441219246566431788414277587183624484845351111624500646035107614221756706581150918776828118482092241867365644233950852801286481603893259029733993572417125002284605243126366683373762688802313288572798197775563793405251353957529601737375987762230223965539018597115373258092875512799931693493522478726661976059512568029782074142871019609980899851702029278565972205831732184397965899892253392769838212803823816067145737697311648549879049613081017925387808738647333178075446683195899683981412014732
# 1
# sign = 12029865785359077271888851642408932941748698222400692402967271078485911077035193062225857653592806498565936667868784327397659271889359852555292426797695393591842279629975530499882434299824406229989496470187187565025826834367095435441393901750671657454855301104151016192695436071059013094114929109806658331209302942624722867961155156665675500638029626815869590842939369327466155186891537025880396861428410389552502395963071259114101340089657190695306100646728391832337848064478382298002033457224425654731106858054291015385823564302151351406917158392454536296555530524352049490745470215338669859669599380477470525863815

分析可得下面的关系:

  1. $WHATF = (d^3 + 3) \space mod \space phi$
  2. $m = (flag*r^{e^2+d^2}) \space mod \space n$
  3. $sign = m^d \space mod \space n$

根据关系式2,两边加上d次方:

$m^d = (flag^d*r^{e(ed)}*r^{d^3}) \space mod \space n$

用欧拉定理进行化简:

$m^d = (flag^d)r^er^{WHATF-3} \space mod \space n$

据此可以求出$flag^d$,再带上e次方并再次利用欧拉定理即为flag。

r还未分析:

def gift():
    assert t > 0
    gift = pow(r,t) - 1
    #print(t)
    print(isPrime(gift))

$r^t-1$是素数,分情况讨论:

当$t==1$,则$r=一个素数+1$,那么r有无限中情况;

当$t!=1$,$r^t-1可分解为*r^t−1=(r−1)(r^{t−1}+r^{t−2}+⋯+r+1)$,这个数想要为素数,那么$r-1$肯定等于$1$,即$r==2$。

r解出来了,开始敲代码:

e = 0x10001
n = ...
WHATF= ...
sign = ...

r = 2
flagd = sign * inverse(pow(r,e+WHATF-3,n),n)
flag = pow(flagd,e,n)
print(long_to_bytes(flag))
#b'DASCTF{RSA_Bl1nd_Signatur3_With_M4th}'

ECC

from Crypto.Util.number import *
from secret import flag, p, q, a, b, e1, e2, e3

assert isPrime(p) and isPrime(q)
assert flag.startswith("DASCTF{") and flag.endswith("}")

class ECC():
    def __init__(self, a, b, p, q, e):
        self.p, self.q = p, q
        self.a, self.b = a, b
        self.N         = p * q
        self.e         = e
        self.Kbits     = 8
        self.Ep        = EllipticCurve(IntegerModRing(p), [a, b])
        self.Eq        = EllipticCurve(IntegerModRing(q), [a, b])

        N1 = self.Ep.order()
        N2 = 2 * p + 2 - N1
        N3 = self.Eq.order()
        N4 = 2 * q + 2 - N3

        self.d = {
            ( 1,  1): inverse_mod(e, lcm(N1, N3)),
            ( 1, -1): inverse_mod(e, lcm(N1, N4)),
            (-1,  1): inverse_mod(e, lcm(N2, N3)),
            (-1, -1): inverse_mod(e, lcm(N2, N4))
        }

        self.E = EllipticCurve(IntegerModRing(self.N), [a, b])

    def enc(self, plaintext):
        msg_point = self.msg_to_point(plaintext, True)
        mp = self.Ep(msg_point)
        mq = self.Eq(msg_point)
        cp = (self.e * mp).xy()
        cq = (self.e * mq).xy()
        cp = (int(cp[0]), int(cp[1]))
        cq = (int(cq[0]), int(cq[1]))
        c  = (int(crt([cp[0], cq[0]], [self.p, self.q])), \
              int(crt([cp[1], cq[1]], [self.p, self.q])))
        c = self.E(c)
        return c.xy()

    def dec(self, ciphertext):
        x = ciphertext
        w = x^3 + self.a*x + self.b % self.N

        P.<Yp> = PolynomialRing(Zmod(self.p))
        fp = x^3 + self.a*x + self.b -Yp^2
        yp = fp.roots()[0][0]

        P.<Yq> = PolynomialRing(Zmod(self.q))
        fq = x^3 + self.a*x + self.b -Yq^2
        yq = fq.roots()[0][0]

        y = crt([int(yp), int(yq)], [self.p, self.q])

        cp, cq = self.Ep((x, y)), self.Eq((x, y))
        legendre_symbol_p = legendre_symbol(w, self.p)
        legendre_symbol_q = legendre_symbol(w, self.q)

        mp = (self.d[(legendre_symbol_p, legendre_symbol_q)] * cp).xy()
        mq = (self.d[(legendre_symbol_p, legendre_symbol_q)] * cq).xy()

        return crt([int(mp[0]), int(mq[0])], [self.p, self.q]) >> self.Kbits

    def msg_to_point(self, x, shift=False):
        if shift:
            x <<= self.Kbits
        res_point = None
        for _ in range(2 << self.Kbits):
            P.<Yp> = PolynomialRing(Zmod(self.p))
            fp = x^3 + self.a*x + self.b - Yp^2
            P.<Yq> = PolynomialRing(Zmod(self.q))
            fq = x^3 + self.a*x + self.b - Yq^2
            try:
                yp, yq = int(fp.roots()[0][0]), int(fq.roots()[0][0])
                y = crt([yp, yq], [self.p, self.q])
                E = EllipticCurve(IntegerModRing(self.p*self.q), [self.a, self.b])
                res_point = E.point((x, y))
                return res_point
            except:
                x += 1
        return res_point


ecc1 = ECC(a, b, p, q, e1)
ecc2 = ECC(a, b, p, q, e2)
ecc3 = ECC(a, b ,p, q, e3)
gift = p * q * getPrime(1000)

secret = bytes_to_long(flag[7:-1].encode())
ciphertext1 = ecc1.enc(secret)
ciphertext2 = ecc2.enc(secret)
ciphertext3 = ecc3.enc(secret)

with open("output.txt", "w") as f:
    
    f.write(f"e1 = {e1}\n")
    f.write(f"e2 = {e2}\n")
    f.write(f"e3 = {e3}\n")
    f.write(f"gift = {gift}\n")
    f.write(f"C1 = {ciphertext1}\n")
    f.write(f"C2 = {ciphertext2}\n")
    f.write(f"C3 = {ciphertext3}\n")

定义了三个椭圆曲线,a、b、n都没给,所以先想办法求a、b。

引入Gröbner基理论工具。知识有限,大致了解就是,可用于计算多项式环中的基础元素,即解一般的多项式方程组,包括非线性方程组和多项式不定方程。对于大型或高阶方程组,可能得不到结果。且目标多项式方程组需要满足一些条件。其中最重要的条件是方程组必须是一个“零维”方程组,也就是说,它必须有有限个解

从题中我们可以列出多项式方程组来:

$f1 = C1[0]^3 + aC1[0] + b - C1[1]^2$

$f2 = C2[0]^3 + aC2[0] + b - C2[1]^2$

$f3 = C3[0]^3 + aC3[0] + b - C3[1]^2$

gift = ...
P.<a,b>=PolynomialRing(Zmod(gift))
C1 = (..., ...)
C2 = (..., ...)
C3 = (...,...)

f1 = C1[0]^3 + a*C1[0] + b - C1[1]^2 
f2 = C2[0]^3 + a*C2[0] + b - C2[1]^2
f3 = C3[0]^3 + a*C3[0] + b - C3[1]^2
F = [f1,f2,f3]
Ideal = Ideal(F)
I = Ideal.groebner_basis()
print(I)
#[a + 6383454939215515141151308275756464378147341998868124849701666287931118728967033226489555343116783930020043447064021757870443190275344745221658277278096846919402186283335931329880274804317278840879511880105400148227288592654329031719888755699046101784104099741865444662504240509089508615358820602230534486420527588876985837918460253592556268354478308719338006099829036747790521589851108766488409474143802894481467371124474, b + 2061828487946313274444567336921027851992389239431896215882831043443098187273467324250117099919991128038110286667574268827149737102849843003427760947370452301720570966798422301991069233423052047573723017573811854447144591388611545295336479676711135093748524215062079916506134402329979650885359052525127585725226235274380415403877926132099800327766309604816799309017969361197829094471646886280677088152723532310326801778432, 1858284081017011776897142483530706248351014197676168270132930318711536519639284920939350511528325590655669305434894548271]

注意这里的结果,为三个一次多项式组,即:

a + 6383454939215515141151308275756464378147341998868124849701666287931118728967033226489555343116783930020043447064021757870443190275344745221658277278096846919402186283335931329880274804317278840879511880105400148227288592654329031719888755699046101784104099741865444662504240509089508615358820602230534486420527588876985837918460253592556268354478308719338006099829036747790521589851108766488409474143802894481467371124474 = 0
b + 2061828487946313274444567336921027851992389239431896215882831043443098187273467324250117099919991128038110286667574268827149737102849843003427760947370452301720570966798422301991069233423052047573723017573811854447144591388611545295336479676711135093748524215062079916506134402329979650885359052525127585725226235274380415403877926132099800327766309604816799309017969361197829094471646886280677088152723532310326801778432 = 0
1858284081017011776897142483530706248351014197676168270132930318711536519639284920939350511528325590655669305434894548271

故a、b相应取相反数,第三个数为n的值。

a、b、n求出来了,构造曲线:$E=EllipticCurve(Zmod(n),[a,b])$

再来看加密函数,有$c = e*m$,这个数乘运算是在ECC上点的运算。现有同一个m用三组不同e加密得到的c,这可以类比rsa的共模攻击,第一次在ECC与RSA结合中遇到共模攻击,很有必要作下对比,先看常规共模的解题方式:

s = gcdext(e1,e2)#扩展欧几里得算法,得到x,y,即ax+by=gcd(a,b)

m1 = pow(c1,s[1],n1)
m2 = pow(c2,s[2],n1)
m = (m1 * m2) % n1
print(long_to_bytes(m))
#运用的前提的是gcd(e1,e2) == 1

而在此题中,有$gcd(e1,e3) == 1$,故计算$gcdext(e1,e3)$

E1=E(C1[0],C1[1])
E3=E(C3[0],C1[1])
#这里是计算椭圆曲线上的点,用于计算
s = gcdext(e1,e3)
m1 = s[1]*E1 
m3 = s[2]*E3
m = m1 + m3
print(m)
#(568187760467717269610985553206613709901686770919725280411069329483654912 : 902383579564357536192281359415338858998812047575951055596174651153047572493238086026951049981445179941533576636231499174 : 1)
print(long_to_bytes(568187760467717269610985553206613709901686770919725280411069329483654912))
#b'RSA_0n_ECC_1s_mor3_Ineres7ing\x00'

主要区分点:

$m1 = s[1]*E1$
$m3 = s[2]*E3$
$m = m1 + m3$

这得根据加密所用的公式而定。

其余两题暂时放着?😅


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1666739907@qq.com
github