naby

导航

SCTF2024-crypto

因为解出了所有密码,故发一篇wp吗,都是脚本,没讲原理。(还有一题问卷,其他都没做(出来)

(虽然都是简单题,虽然都是能找到脚本的题,虽然我都不会,虽然我不会格,但你就说我解没解没解出来吧)

(感谢鸡块师傅,太崇拜了)

Signin

xyctf中的factor3

(只能说,xyctf的含金量还在提高)

鸡块师傅的博客:2024-XYCTF-wp-crypto | 糖醋小鸡块的blog (tangcuxiaojikuai.xyz)

能够得(猜)到如下式子:

\(ed=1+k(p^2+p+1)(q^2+q+1)\)

\(ed=1+k*(N^2+p^2q+p^2+pq^2+N+p+q^2+q+1)\\\)

合并同类型得到:

\(ed=1+k[n^2+n+1+n(p+q)+(p+q)^2+(p+q)^2-2n+p+q]\)

最后得到:

\(ed=1+k[n^2-n+1+(n+1)(p+q)+(p+q)^2]\)

令x=k,y=p+q,得到模e下的多项式

\(f=1+x[n^2-n+1+(n+1)y+y^2]\)

"""from sage.all import *
from Crypto.Util.number import *
from hashlib import md5

class RSA():
    def __init__(self, nbits):
        self.nbits = nbits
        self.p, self.q = self.getPrimes()
        self.n = self.p*self.q
        self.Gift = self.Gift()
        self.priv, self.pub = self.keyGen()
        
    
    def getPrimes(self):
        nbits = self.nbits
        p = random_prime(2^(nbits-1),lbound=2^(nbits-2))
        q = random_prime(2^(nbits-1),lbound=2^(nbits-2))
        while p == q:
            q = random_prime(2^(nbits-1),lbound=2^(nbits-2))
        return p,q
    
    def Gift(self):
        p,q = self.p, self.q
        return (p^2 + p + 1)*(q^2 + q + 1)
    
    def keyGen(self):
        nbits = self.nbits
        while True:
            d = randint(2^(nbits//4),2^(nbits//2))
            if gcd(d,self.Gift) != 1:
                d = randint(2^(nbits//4),2^(nbits//2))
            e = pow(d,-1,self.phi)
            return (self.p,self.q,self.n,e,d),(self.n,e)
    

RRR = RSA(512)

bp = long_to_bytes(int(RRR.p))
FLAG = 'SCTF{'+md5(bp).hexdigest()+'}'


print(f'N = {RRR.n}')
print(f'e = {RRR.pub[1]}')"""
from Crypto.Util.number import *
from gmpy2 import *
import itertools

def small_roots(f, bounds, m=1, d=None):
    if not d:
        d = f.degree()

    R = f.base_ring()
    N = R.cardinality()

    f /= f.coefficients().pop(0)
    f = f.change_ring(ZZ)

    G = Sequence([], f.parent())
    for i in range(m + 1):
        base = N ^ (m - i) * f ^ i
        for shifts in itertools.product(range(d), repeat=f.nvariables()):
            g = base * prod(map(power, f.variables(), shifts))
            G.append(g)

    B, monomials = G.coefficient_matrix()
    monomials = vector(monomials)

    factors = [monomial(*bounds) for monomial in monomials]
    for i, factor in enumerate(factors):
        B.rescale_col(i, factor)

    B = B.dense_matrix().LLL()

    B = B.change_ring(QQ)
    for i, factor in enumerate(factors):
        B.rescale_col(i, 1 / factor)

    H = Sequence([], f.parent().change_ring(QQ))
    for h in filter(None, B * monomials):
        H.append(h)
        I = H.ideal()
        if I.dimension() == -1:
            H.pop()
        elif I.dimension() == 0:
            roots = []
            for root in I.variety(ring=ZZ):
                root = tuple(R(root[var]) for var in f.variables())
                roots.append(root)
            return roots

    return []

n = 32261421478213846055712670966502489204755328170115455046538351164751104619671102517649635534043658087736634695616391757439732095084483689790126957681118278054587893972547230081514687941476504846573346232349396528794022902849402462140720882761797608629678538971832857107919821058604542569600500431547986211951
e = 334450817132213889699916301332076676907807495738301743367532551341259554597455532787632746522806063413194057583998858669641413549469205803510032623432057274574904024415310727712701532706683404590321555542304471243731711502894688623443411522742837178384157350652336133957839779184278283984964616921311020965540513988059163842300284809747927188585982778365798558959611785248767075169464495691092816641600277394649073668575637386621433598176627864284154484501969887686377152288296838258930293614942020655916701799531971307171423974651394156780269830631029915305188230547099840604668445612429756706738202411074392821840

PR.<x,y>=PolynomialRing(Zmod(e))
f = 1 + x*(n^2-n+1 + (n+1)*y + y^2)
res = small_roots(f, (2^256,2^512), m=2, d=3)

pplusq = int(res[0][1])
pminusq = iroot(pplusq^2-4*n,2)[0]
p = (pplusq + pminusq) // 2
q = n // p


from hashlib import md5
print('SCTF{'+md5(long_to_bytes(int(p))).hexdigest()+'}')   #SCTF{12899cda850fc484de8bce978839620d}
print('SCTF{'+md5(long_to_bytes(int(q))).hexdigest()+'}')

不完全阻塞干扰

一部分加密代码

msg = bytes_to_long(FLAG)
n = p^5*q^2
phi = p^4*(p-1)*q*(q-1)
e = 65537
d = inverse(d,phi)
c = pow(m,e,n)

证书分析,拿有效数据解base64转hex,中间一大段A就是d缺失的数据

-----BEGIN RSA PRIVATE KEY-----
MIIIFQKCA4AGfwqk6XSmOh/+jVwj5dPEMWU65BzHRvMF9iqfGT8iSGy37xsnVjSB
j0bQdSpROeGZGCcfoNfSe8Zg0rckFNCOpSyIN/lJx7rswwKboxcn7zvxINmSbALX
QS8YfpjcVt0HuYfSzBka1WFkoUTyiy9woV0QVYik8n+7KJH8UnvWiQpfeVtcSEdq
a/nftnt+Hrx7Gwhs0otYxolVv99E7M4R/6zfZUVRsVm3gyBAzCjujr6kj4Zy1T49
6I/Pu1+ydrUDiA3TTVmTM13fjMuWwbTXn1AtchBHZa2cKxhYoXrz1b5E+jy/S47r
lCqjlCo4cdLGWscCiRI/wun5sly/y9eEEJYGD6UEw6B7WRSTxkyI0LtFKFqFtffV
nbmPqgDCzT+7Y9pZkgXxyrDfUs97QxoO5KfjVpZUbOnQPvWV7O6S0hQskul9J0ST
lwNFW0xw3sJ8Mh7GuDwCliLoOp4NVdCyWNldTmEpGGXdp23GGfzpV3mQQpxud+nU
B4HjsvRJcBuD6LDGxm6zgPlkc+XUIu/uiysOiLcWsAp5ydUUyjrZ0t7lJmCf+VQX
MqQZjRG52/uy5Vwk2A6lItB4bjNV8jYGpdOKct5O78i2v8SCJIooYstp2ODj0xZZ
fanYCCi+hQVPrxX8NpyqyvuBXGlzwXGUBoPVahoZZ7Cbf/o/vlsuCGmXWdhNcWA/
UWRHaWuycyKmnzn2yiU+ANyVVdX5cygHDEZ/NmPMSJqtEw8oxC81v4jFcZIKuSrL
j3XQPjWnUQPFvZbwYclr0Cr24dGRsN0WS8chN3AD7b9dPvZaXpBGOFNWtSFiO+43
8WSFCgp6+w7U5+i9mv4SmPfVMrya2UGBLTMq7OddHMyx/2n9QrMfJIrledng1qFL
BUbnhLqUDjK9AcOV34/0WEBARitUefoHM21QPcMy5w/AbZRjKX/AQrYj1W+H76pS
WptYDjFNkNEhGJPtQHomUI3qoKE8nujJArnhw6Av6aUUUsAu573MhcDv9jiR4kcD
vSZdnJ2/RW4q+UCVOLzg/sx+urICZqqrBsdmw+ps2py5ul4dAkt9w9c+dvajMxl7
rYfE+zTVZaABSqxygl5Brc/q2tyHrO9ArYS3xVaRq61WG+BVDqCpiEcMQnQyrLj+
srnS0lmPsgibuRu9nLGZ6JLTYWTYvz7NVFdqlxNAR6EtqEIHSFu05QIDAQABAoID
gAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoGBAIBj0KIYduXOHiEB
wgAVUpBm7Zl2iC0QAqKe/g8v38wnQ/yaS1tlHMlxCGmeyi+x89kxdbrjQ+fJLkpB
xy0F5XAZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAoGBAOTw/kn5rhSSwJegqYj6cYdmJf5PzgWw
IE8f30PsZLTaxpnSjhZu/fx1YtGeWMNJPZEANlzyhAtGwPbujZZIBxcP8sE8TrgB
LsqzeGKjkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAA


30
82 0815

n
02 82 0380 
067f0aa4e974a63a1ffe8d5c23e5d3c431653ae41cc746f305f62a9f193f22486cb7ef1b275634818f46d0752a5139e19918271fa0d7d27bc660d2b72414d08ea52c8837f949c7baecc3029ba31727ef3bf120d9926c02d7412f187e98dc56dd07b987d2cc191ad56164a144f28b2f70a15d105588a4f27fbb2891fc527bd6890a5f795b5c48476a6bf9dfb67b7e1ebc7b1b086cd28b58c68955bfdf44ecce11ffacdf654551b159b7832040cc28ee8ebea48f8672d53e3de88fcfbb5fb276b503880dd34d5993335ddf8ccb96c1b4d79f502d72104765ad9c2b1858a17af3d5be44fa3cbf4b8eeb942aa3942a3871d2c65ac70289123fc2e9f9b25cbfcbd7841096060fa504c3a07b591493c64c88d0bb45285a85b5f7d59db98faa00c2cd3fbb63da599205f1cab0df52cf7b431a0ee4a7e35696546ce9d03ef595ecee92d2142c92e97d2744939703455b4c70dec27c321ec6b83c029622e83a9e0d55d0b258d95d4e61291865dda76dc619fce9577990429c6e77e9d40781e3b2f449701b83e8b0c6c66eb380f96473e5d422efee8b2b0e88b716b00a79c9d514ca3ad9d2dee526609ff9541732a4198d11b9dbfbb2e55c24d80ea522d0786e3355f23606a5d38a72de4eefc8b6bfc482248a2862cb69d8e0e3d316597da9d80828be85054faf15fc369caacafb815c6973c171940683d56a1a1967b09b7ffa3fbe5b2e08699759d84d71603f516447696bb27322a69f39f6ca253e00dc9555d5f97328070c467f3663cc489aad130f28c42f35bf88c571920ab92acb8f75d03e35a75103c5bd96f061c96bd02af6e1d191b0dd164bc721377003edbf5d3ef65a5e9046385356b521623bee37f164850a0a7afb0ed4e7e8bd9afe1298f7d532bc9ad941812d332aece75d1cccb1ff69fd42b31f248ae579d9e0d6a14b0546e784ba940e32bd01c395df8ff4584040462b5479fa07336d503dc332e70fc06d9463297fc042b623d56f87efaa525a9b580e314d90d1211893ed407a26508deaa0a13c9ee8c902b9e1c3a02fe9a51452c02ee7bdcc85c0eff63891e24703bd265d9c9dbf456e2af9409538bce0fecc7ebab20266aaab06c766c3ea6cda9cb9ba5e1d024b7dc3d73e76f6a333197bad87c4fb34d565a0014aac72825e41adcfeadadc87acef40ad84b7c55691abad561be0550ea0a988470c427432acb8feb2b9d2d2598fb2089bb91bbd9cb199e892d36164d8bf3ecd54576a97134047a12da84207485bb4e5

e
02 03
010001

d....

p
AoGBAIBj0KIYduXOHiEBwgAVUpBm7Zl2iC0QAqKe/g8v38wnQ/yaS1tlHMlxCGmeyi+x89kxdbrjQ+fJLkpBxy0F5XAZQ
02 8181 
008063d0a21876e5ce1e2101c20015529066ed9976882d1002a29efe0f2fdfcc2743fc9a4b5b651cc97108699eca2fb1f3d93175bae343e7c92e4a41c72d05e57019


q
AoGBAOTw/kn5rhSSwJegqYj6cYdmJf5PzgWwIE8f30PsZLTaxpnSjhZu/fx1YtGeWMNJPZEANlzyhAtGwPbujZZIBxcP8sE8TrgBLsqzeGKjk
02 8181
00e4f0fe49f9ae1492c097a0a988fa71876625fe4fce05b0204f1fdf43ec64b4dac699d28e166efdfc7562d19e58c3493d9100365cf2840b46c0f6ee8d964807170ff2c13c4eb8012ecab37862a3

分析出来之后就是p高位和q高位,二元copper就行了

from Crypto.Util.number import *
from gmpy2 import *
import itertools

def small_roots(f, bounds, m=1, d=None):
    if not d:
        d = f.degree()

    R = f.base_ring()
    N = R.cardinality()

    f /= f.coefficients().pop(0)
    f = f.change_ring(ZZ)

    G = Sequence([], f.parent())
    for i in range(m + 1):
        base = N ^ (m - i) * f ^ i
        for shifts in itertools.product(range(d), repeat=f.nvariables()):
            g = base * prod(map(power, f.variables(), shifts))
            G.append(g)

    B, monomials = G.coefficient_matrix()
    monomials = vector(monomials)

    factors = [monomial(*bounds) for monomial in monomials]
    for i, factor in enumerate(factors):
        B.rescale_col(i, factor)

    B = B.dense_matrix().LLL()

    B = B.change_ring(QQ)
    for i, factor in enumerate(factors):
        B.rescale_col(i, 1 / factor)

    H = Sequence([], f.parent().change_ring(QQ))
    for h in filter(None, B * monomials):
        H.append(h)
        I = H.ideal()
        if I.dimension() == -1:
            H.pop()
        elif I.dimension() == 0:
            roots = []
            for root in I.variety(ring=ZZ):
                root = tuple(R(root[var]) for var in f.variables())
                roots.append(root)
            return roots

    return []



n=0x067f0aa4e974a63a1ffe8d5c23e5d3c431653ae41cc746f305f62a9f193f22486cb7ef1b275634818f46d0752a5139e19918271fa0d7d27bc660d2b72414d08ea52c8837f949c7baecc3029ba31727ef3bf120d9926c02d7412f187e98dc56dd07b987d2cc191ad56164a144f28b2f70a15d105588a4f27fbb2891fc527bd6890a5f795b5c48476a6bf9dfb67b7e1ebc7b1b086cd28b58c68955bfdf44ecce11ffacdf654551b159b7832040cc28ee8ebea48f8672d53e3de88fcfbb5fb276b503880dd34d5993335ddf8ccb96c1b4d79f502d72104765ad9c2b1858a17af3d5be44fa3cbf4b8eeb942aa3942a3871d2c65ac70289123fc2e9f9b25cbfcbd7841096060fa504c3a07b591493c64c88d0bb45285a85b5f7d59db98faa00c2cd3fbb63da599205f1cab0df52cf7b431a0ee4a7e35696546ce9d03ef595ecee92d2142c92e97d2744939703455b4c70dec27c321ec6b83c029622e83a9e0d55d0b258d95d4e61291865dda76dc619fce9577990429c6e77e9d40781e3b2f449701b83e8b0c6c66eb380f96473e5d422efee8b2b0e88b716b00a79c9d514ca3ad9d2dee526609ff9541732a4198d11b9dbfbb2e55c24d80ea522d0786e3355f23606a5d38a72de4eefc8b6bfc482248a2862cb69d8e0e3d316597da9d80828be85054faf15fc369caacafb815c6973c171940683d56a1a1967b09b7ffa3fbe5b2e08699759d84d71603f516447696bb27322a69f39f6ca253e00dc9555d5f97328070c467f3663cc489aad130f28c42f35bf88c571920ab92acb8f75d03e35a75103c5bd96f061c96bd02af6e1d191b0dd164bc721377003edbf5d3ef65a5e9046385356b521623bee37f164850a0a7afb0ed4e7e8bd9afe1298f7d532bc9ad941812d332aece75d1cccb1ff69fd42b31f248ae579d9e0d6a14b0546e784ba940e32bd01c395df8ff4584040462b5479fa07336d503dc332e70fc06d9463297fc042b623d56f87efaa525a9b580e314d90d1211893ed407a26508deaa0a13c9ee8c902b9e1c3a02fe9a51452c02ee7bdcc85c0eff63891e24703bd265d9c9dbf456e2af9409538bce0fecc7ebab20266aaab06c766c3ea6cda9cb9ba5e1d024b7dc3d73e76f6a333197bad87c4fb34d565a0014aac72825e41adcfeadadc87acef40ad84b7c55691abad561be0550ea0a988470c427432acb8feb2b9d2d2598fb2089bb91bbd9cb199e892d36164d8bf3ecd54576a97134047a12da84207485bb4e5
e=0x10001
c=145554802564989933772666853449758467748433820771006616874558211691441588216921262672588167631397770260815821197485462873358280668164496459053150659240485200305314288108259163251006446515109018138298662011636423264380170119025895000021651886702521266669653335874489612060473962259596489445807308673497717101487224092493721535129391781431853820808463529747944795809850314965769365750993208968116864575686200409653590102945619744853690854644813177444995458528447525184291487005845375945194236352007426925987404637468097524735905540030962884807790630389799495153548300450435815577962308635103143187386444035094151992129110267595908492217520416633466787688326809639286703608138336958958449724993250735997663382433125872982238289419769011271925043792124263306262445811864346081207309546599603914842331643196984128658943528999381048833301951569809038023921101787071345517702911344900151843968213911899353962451480195808768038035044446206153179737023140055693141790385662942050774439391111437140968754546526191031278186881116757268998843581015398070043778631790328583529667194481319953424389090869226474999123124532354330671462280959215310810005231660418399403337476289138527331553267291013945347058144254374287422377547369897793812634181778309679601143245890494670013019155942690562552431527149178906855998534415120428884098317318129659099377634006938812654262148522236268027388683027513663867042278407716812565374141362015467076472409873946275500942547114202939578755575249750674734066843408758067001891408572444119999801055605577737379889503505649865554353749621313679734666376467890526136184241450593948838055612677564667946098308716892133196862716086041690426537245252116765796203427832657608512488619438752378624483485364908432609100523022628791451171084583484294929190998796485805496852608557456380717623462846198636093701726099310737244471075079541022111303662778829695340275795782631315412134758717966727565043332335558077486037869874106819581519353856396937832498623662166446395755447101393825864584024239951058366713573567250863658531585064635727070458886746791722270803893438211751165831616861912569513431821959562450032831904268205845224077709362068478

hp=0x008063d0a21876e5ce1e2101c20015529066ed9976882d1002a29efe0f2fdfcc2743fc9a4b5b651cc97108699eca2fb1f3d93175bae343e7c92e4a41c72d05e57019
hq=0x00e4f0fe49f9ae1492c097a0a988fa71876625fe4fce05b0204f1fdf43ec64b4dac699d28e166efdfc7562d19e58c3493d9100365cf2840b46c0f6ee8d964807170ff2c13c4eb8012ecab37862a3

hp=hp<<504
hq=hq<<408

PR.<x,y>=PolynomialRing(Zmod(n))
f = (hp+x)^5*(hq+y)^2-n
res = small_roots(f, (2^504,2^408), m=2, d=3)

p=int(hp+res[0][0])
q=int(hq+res[0][1])

print(long_to_bytes(int(pow(c,invert(e,p^4*(p-1)*q*(q-1)),n))))
#SCTF{0ne_4rgum3nt_1s_r0tt3n_0r4ng3s,_th3_wh0le_cert1fic4t3_1s_r0tt3n_0r4ng3s:XD}

Whisper

cert1.pem

-----BEGIN PUBLIC KEY-----
MIIBHjANBgkqhkiG9w0BAQEFAAOCAQsAMIIBBgKBgBtdT+CqZ4LiddTOEqbVdWLv
u+fbb1J3JVuJFym/oqGNPttJhD15iaN7lRa+LfjKk5BY5l9ktfsgcb6k9fjROSiV
syvwN32Z9PeZeRJeXbAc21CAocLWZcmsMbWCMCVJnJUTJ3uuXnqEbNJxxDluK6IZ
Ag5YqQVcsYoo02oAv3F7AoGAB59czGZXZ7SiV+XB/1bpgD3y5WUDAtqtQgEF/mck
R3Q70/C+ocRqSYeTLpqIbKh6ev13lqvx5WKcSYb+TyLonNznq7BmJEZRRqLitsqa
sxls6rdGeXTB3EVgiiAEEbKR/a+Z99gNzk2zVm9Kni5XTGIkzQfYBjjSj3ggvPS0
kUM=
-----END PUBLIC KEY-----

cert2.pem

-----BEGIN PUBLIC KEY-----
MIIBHjANBgkqhkiG9w0BAQEFAAOCAQsAMIIBBgKBgAccMk6HaUkxh8FfctXMaVcp
tISI7j+9AdsA1cR48Ix88yCTumF0UFHT6dFpUjqpFDgYH0dnmv9e3SKVD3Sh6xRD
MgqqXZf1wegbXvmj5pumaavExsS0BfUIimA6dPm874iCO0UjV0EUyBBgCDhygZb4
5eDUru7qt53YaDpy88AXAoGAB59czGZXZ7SiV+XB/1bpgD3y5WUDAtqtQgEF/mck
R3Q70/C+ocRqSYeTLpqIbKh6ev13lqvx5WKcSYb+TyLonNznq7BmJEZRRqLitsqa
sxls6rdGeXTB3EVgiiAEEbKR/a+Z99gNzk2zVm9Kni5XTGIkzQfYBjjSj3ggvPS0
kUM=
-----END PUBLIC KEY-----

题目描述

Two public key certificates were monitored. And Mr. Dual intercepted a ciphertext. Just when he was in the rough, a Careless Whisper told that the length of a key parameter is carelessly set to 345 bits.

密文的16进制数据

15aadf434f05fc47e06f6997a554c1de7cecdad1faf40a74bc7c6d7c4c5fa533fe2c605bcde6acaa0ee3576f607be6503831b33d54928eaad1f8d64187cff8f4f1a67ff6d846715bfc4795b22e216ec7ec92106db6a1fdeb9d649968a81cbb10a3e5c828167af2fd0e81534f11198b63caad0ed8e9f844db8403027ba3eb1a56

是dual rsa,我没见过的东西,所以搜索引擎启动。

我自己能想到连分数处理的,但是写不出来,找了一篇博客https://hasegawaazusa.github.io/dual-rsa-note.html,但也解不出来,然后就开始,找脚本啊找脚本,找到一个好脚本。

参数什么的没动,n1,n2,e可以手工读公钥文件提取(因为我n2无法直接读)

(贴给gpt让它将py2转成py3就行了)

https://elliptic-shiho.github.io/ctf-writeups/#!ctf/2017/0CTF Finals/cr1000-AuthenticationSecrecy/README.md

from sage.all import *
import math
from Crypto.Util.number import *

# display matrix picture with 0 and X
def matrix_overview(BB):
    for ii in range(BB.dimensions()[0]):
        a = '{:02d} '.format(ii)
        for jj in range(BB.dimensions()[1]):
            a += ' ' if BB[ii, jj] == 0 else 'X'
            if BB.dimensions()[0] < 60:
                a += ' '
        print(a)

def dual_rsa_liqiang_et_al(e, n1, n2, delta, mm, tt):
    N = (n1 + n2) // 2
    A = ZZ(math.floor(N**0.5))

    _XX = ZZ(math.floor(N**delta))
    _YY = ZZ(math.floor(N**0.5))
    _ZZ = ZZ(math.floor(N**(delta - 1./4)))
    _UU = _XX * _YY + 1

    M = Matrix(ZZ, [[A, e], [0, n1]])
    B = M.LLL()
    l11, l12 = B[0]
    l21, l22 = B[1]
    l_11 = ZZ(l11 / A)
    l_21 = ZZ(l21 / A)

    modulo = e * l_21
    F = Zmod(modulo)

    PR = PolynomialRing(F, 'u, x, y, z')
    u, x, y, z = PR.gens()

    PK = PolynomialRing(ZZ, 'uk, xk, yk, zk')
    uk, xk, yk, zk = PK.gens()

    PQ = PK.quo(xk * yk + 1 - uk)
    f = PK(x * (n2 + y) - e * l_11 * z + 1)
    fbar = PQ(f).lift()

    gijk = {}
    for k in range(mm + 1):
        for i in range(mm - k + 1):
            for j in range(mm - k - i + 1):
                gijk[i, j, k] = PQ(xk**i * zk**j * PK(fbar)**k * modulo**(mm - k)).lift()

    hjkl = {}
    for j in range(1, tt + 1):
        for k in range(math.floor(mm / tt) * j, mm + 1):
            for l in range(k + 1):
                hjkl[j, k, l] = PQ(yk**j * zk**(k - l) * PK(fbar)**l * modulo**(mm - l)).lift()

    monomials = []
    for k in gijk.keys():
        monomials += gijk[k].monomials()
    for k in hjkl.keys():
        monomials += hjkl[k].monomials()

    monomials = sorted(set(monomials), reverse=True)
    assert len(monomials) == len(gijk) + len(hjkl)
    dim = len(monomials)

    M = Matrix(ZZ, dim)
    row = 0
    for k in gijk.keys():
        for i, monomial in enumerate(monomials):
            M[row, i] = gijk[k].monomial_coefficient(monomial) * monomial.subs(uk=_UU, xk=_XX, yk=_YY, zk=_ZZ)
        row += 1
    for k in hjkl.keys():
        for i, monomial in enumerate(monomials):
            M[row, i] = hjkl[k].monomial_coefficient(monomial) * monomial.subs(uk=_UU, xk=_XX, yk=_YY, zk=_ZZ)
        row += 1

    matrix_overview(M)
    print('=' * 128)

    B = M.LLL()
    matrix_overview(B)

    H = [(i, 0) for i in range(dim)]
    H = dict(H)
    for j in range(dim):
        for i in range(dim):
            H[i] += PK((monomials[j] * B[i, j]) / monomials[j].subs(uk=_UU, xk=_XX, yk=_YY, zk=_ZZ))
    H = list(H.values())

    PQ = PolynomialRing(QQ, 'uq, xq, yq, zq')
    uq, xq, yq, zq = PQ.gens()

    for i in range(dim):
        H[i] = PQ(H[i].subs(uk=xk * yk + 1))

    I = Ideal(*H[1:20])
    g = I.groebner_basis('giac')[::-1]
    mon = [t.monomials() for t in g]

    PX = PolynomialRing(ZZ, 'xs')
    xs = PX.gen()

    x_pol = y_pol = z_pol = None

    for i in range(len(g)):
        if mon[i] == [xq, 1]:
            print(g[i] / g[i].lc())
            x_pol = g[i] / g[i].lc()
        elif mon[i] == [yq, 1]:
            print(g[i] / g[i].lc())
            y_pol = g[i] / g[i].lc()
        elif mon[i] == [zq, 1]:
            print(g[i] / g[i].lc())
            z_pol = g[i] / g[i].lc()

    if x_pol is None or y_pol is None or z_pol is None:
        print('[-] Failed: we cannot get a solution...')
        return

    x0 = x_pol.subs(xq=xs).roots()[0][0]
    y0 = y_pol.subs(yq=xs).roots()[0][0]
    z0 = z_pol.subs(zq=xs).roots()[0][0]

    assert f(x0 * y0 + 1, x0, y0, z0) % modulo == 0

    a0 = z0
    a1 = (x0 * (n2 + y0) + 1 - e * l_11 * z0) / (e * l_21)

    d = a0 * l_11 + a1 * l_21
    return d

if __name__ == '__main__':
    delta = 0.334
    mm = 4
    tt = 2

    n1=0x1b5d4fe0aa6782e275d4ce12a6d57562efbbe7db6f5277255b891729bfa2a18d3edb49843d7989a37b9516be2df8ca939058e65f64b5fb2071bea4f5f8d1392895b32bf0377d99f4f79979125e5db01cdb5080a1c2d665c9ac31b5823025499c9513277bae5e7a846cd271c4396e2ba219020e58a9055cb18a28d36a00bf717b
    n2=0x071c324e8769493187c15f72d5cc695729b48488ee3fbd01db00d5c478f08c7cf32093ba61745051d3e9d169523aa91438181f47679aff5edd22950f74a1eb1443320aaa5d97f5c1e81b5ef9a3e69ba669abc4c6c4b405f5088a603a74f9bcef88823b4523574114c810600838728196f8e5e0d4aeeeeab79dd8683a72f3c017
    e=0x079f5ccc665767b4a257e5c1ff56e9803df2e5650302daad420105fe672447743bd3f0bea1c46a4987932e9a886ca87a7afd7796abf1e5629c4986fe4f22e89cdce7abb06624465146a2e2b6ca9ab3196ceab7467974c1dc45608a200411b291fdaf99f7d80dce4db3566f4a9e2e574c6224cd07d80638d28f7820bcf4b49143

    d1 = dual_rsa_liqiang_et_al(e, n1, n2, delta, mm, tt)



    c=open('ciphertext.txt','rb').read()
    c=bytes_to_long(c)

    flag=long_to_bytes(int(pow(c,int(d1),n1)))
    if b"SCTF" in flag:
        print(flag)


# https://elliptic-shiho.github.io/ctf-writeups/#!ctf/2017/0CTF%20Finals/cr1000-AuthenticationSecrecy/README.md
# b'SCTF{Ju5t_3njoy_th3_Du4l_4nd_Copper5m1th_m3thod_w1th_Ur_0wn_1mplem3nt4t10n}'

LinearARTs

from random import choices
import json
from sage.all import *
from Crypto.Util.number import *
from sage.groups.perm_gps.permgroup_named import SymmetricGroup



def Young(FLAG):
    f = int.from_bytes(FLAG, "big")
    q = 65537

    s = []
    while f:
        s.append(f % q)
        f //= q
    s = vector(GF(q), s)

    n, m = len(s), len(s) ** 2

    A = Matrix(GF(q), m, n, lambda i, j: randint(0, q - 1))
    e = vector(choices(range(2^8), k=m), GF(q))*Matrix(ZZ,PermutationGroupElement(SymmetricGroup(m).random_element()).matrix())
    b = (A*s) + e


    return A,b


def Old(m, nbits):
    Sn = SymmetricGroup(m)
    p = [getPrime(360) for i in range(m)]
    N = sorted([getRandomNBitInteger(nbits) for _ in range(m)])
    S = []
    for i in range(m):
        r = [N[_] % p[i] for _ in range(m)]
        r = vector(ZZ,r)

        Per = Sn.random_element()
        P = PermutationGroupElement(Per)
        Pm = Matrix(ZZ,P.matrix())
        r *= Pm
        S.append(r)
    S = matrix(ZZ,S)

    with open('Old.matrix','w') as f:
        json.dump({"S": str(list(S)),"p": str(p)}, f)
    
    return N

def chall(nn):
    # The challenge lasted nn rounds
    # Young_level * virtue >= Old_level , where virtue = nn + 1

    h = []
    HP = []
    MP = []
    Old_level = 625*2*2
    Young_level = 25*5*5*2

    M = getPrime(Old_level)
    XP = getRandomRange(1,M)
    for _ in range(nn):
        a = getRandomRange(1,M)
        b = a*XP % M
        HP.append(a)
        MP.append(b)
        delta_level = Old_level - Young_level
        h.append(b >> delta_level << delta_level)


        

    return XP,M,HP,MP,h
    

mm = 16
nn = 9
nbits = 3840


A,b = Young(FLAG)
N = Old(mm, nbits)

XP,M,HP,MP,h = chall(nn)

# MP is useful ,I can use him to cast five lightning spells
D = diagonal_matrix(GF(0x10001),N+MP)
Sn = SymmetricGroup(5*5)
Per = Sn.random_element()

P = PermutationGroupElement(Per)
PM = Matrix(GF(0x10001),P.matrix())




AA = A*D*PM

with open('D.matrix','w') as f:
    json.dump({"D": str(list(D))}, f)



# OK! Find your martial arts, and then you can get the flag.


with open("output.txt", "w") as f:
    json.dump({"AA": str(list(AA)), "b": str(b)}, f)


print(f'My SymmetricGroup is {Sn}, and my element is {Per}')
print(f'M = {M}')
print(f'h = {h}')
print(f'HP = {HP}')



'''
My SymmetricGroup is Symmetric group of order 25! as a permutation group, and my element is (1,23,2,13,3,16,15,6,22,18,14,4,25,11,20,24,21,9,5,17,7,19,10,12,8)
'''

只需要用到如下数据,其他数据都没用。

关键点在于\(AA = A*D*PM\)

PM可以自己测试一下就可以自己生成了,D也直接给了,AA也有了

那A就可以直接算出来了,其他数据都是杂鱼。

之后看Young中就是一个lwe问题,我不会,所有搜索引擎再次启动。

再次感谢鸡块师傅,最后又是找他的脚本出了

https://tangcuxiaojikuai.xyz/post/758dd33a.html

import json
from Crypto.Util.number import *


with open('D.matrix', 'r') as file:
    data = json.load(file)
    D=eval(data['D'])
    D=Matrix(GF(0x10001),D)

with open('output.txt', 'r') as file:
    data = json.load(file)

    AA=eval(data['AA'])
    AA=Matrix(GF(65537),AA)

    b=list(eval(data['b']))

##### test
if 0:
    Sn = SymmetricGroup(5*5)
    Per = Sn.random_element()
    P = PermutationGroupElement(Per)
    PM = Matrix(GF(0x10001),P.matrix())
    print(Per)
    print(P)
    print(PM)
#My SymmetricGroup is Symmetric group of order 25! as a permutation group, and my element is (1,23,2,13,3,16,15,6,22,18,14,4,25,11,20,24,21,9,5,17,7,19,10,12,8)
P=(1,23,2,13,3,16,15,6,22,18,14,4,25,11,20,24,21,9,5,17,7,19,10,12,8)
PM=[]
for i in range(len(P)):
    PM.append([0]*25)
for i in range(len(P)):
    PM[P[i]-1][P[(i+1)%len(P)]-1]=1
PM=Matrix(GF(0x10001),PM)


AD=PM.solve_left(AA)
A=D.solve_left(AD)


# https://tangcuxiaojikuai.xyz/post/758dd33a.html
def primal_attack2(A,b,m,n,p,esz):
    L = block_matrix(
        [
            [matrix(Zmod(p), A).T.echelon_form().change_ring(ZZ), 0],
            [matrix.zero(m - n, n).augment(matrix.identity(m - n) * p), 0],
            [matrix(ZZ, b), 1],
        ]
    )
    #print(L.dimensions())
    Q = diagonal_matrix([1]*m + [esz])
    L *= Q
    L = L.LLL()
    L /= Q
    res = L[0]
    if(res[-1] == 1):
        e = vector(GF(p), res[:m])
    elif(res[-1] == -1):
        e = -vector(GF(p), res[:m])
    s = matrix(Zmod(p), A).solve_right((vector(Zmod(p), b)-e))
    return s
f=primal_attack2(A,b,625,25,65537,2^8)
print(f)
m=0
for i in range(len(f)):
    m=m+65537^i*int(f[i])
print(long_to_bytes(int(m)))
#b'SCTF{HunYu4n_TaiChi-5tyl3_P3rmut4t10nProup_m4st3r}'

posted on 2024-10-01 09:31  Naby  阅读(62)  评论(0编辑  收藏  举报