2023羊城杯Crypto

2023羊城杯Crypto
首发于
DexterJie’Blog

Danger_RSA

题目:

from Crypto.Util.number import *

m = bytes_to_long(flag)


def get_key(a, nbit):
    assert a >= 2
    while True:
        X = getRandomInteger(nbit // a)
        s = getRandomRange(pow(2, a ** 2 - a + 4), pow(2, a ** 2 - a + 5))
        p = X ** a + s
        if isPrime(p):
            return (p, s)


p, s = get_key(a, 1024)
q, t = get_key(a, 1024)

N = p * q
e = s * t
c = pow(m, e, N)
print("N =", N)
print("e =", e)
print("c =", c)
# N = 
# e = 11079917583
# c = 

根据 p , q p,q p,q的生成方式可知 p = x 4 + s , q = y 4 + t p = x^4+s,q = y^4+t p=x4+s,q=y4+t

根据 e e e的比特大小判断出 a = 4 , s = 17 b i t , t = 17 b i t a=4,s = 17bit,t = 17bit a=4,s=17bit,t=17bit

e e e分解后得到 e = 3 × 7 2 × 19 × 691 × 5741 e = 3\times7^2 \times 19 \times 691 \times 5741 e=3×72×19×691×5741

选出合适的乘积作为 s , t s,t s,t

∴ p = x 4 + s , q = y 4 + t \therefore p =x^4 + s,q = y^4 + t p=x4+s,q=y4+t p ≈ x 4 , q ≈ y 4 p \approx x^4,q \approx y^4 px4,qy4

n ≈ ( x y ) 4 ⟶ x y = n 1 4 n \approx(xy)^4 \longrightarrow xy = n^{\frac{1}{4}} n(xy)4xy=n41

得到 x y xy xy之后

联立 n = ( x 4 + s ) ( y 4 + t ) n = (x^4+s)(y^4+t) n=(x4+s)(y4+t) x × y = x y x\times y = xy x×y=xy

解出 x , y x,y x,y这里要注意的是,s,t要选合适,才有整数解,多试试

然后就能出p,q了,发现 e e e ϕ ( n ) \phi(n) ϕ(n)不互素

处理一下即可

exp:

from Crypto.Util.number import *
import gmpy2

n = 20289788565671012003324307131062103060859990244423187333725116068731043744218295859587498278382150779775620675092152011336913225797849717782573829179765649320271927359983554162082141908877255319715400550981462988869084618816967398571437725114356308935833701495015311197958172878812521403732038749414005661189594761246154666465178024563227666440066723650451362032162000998737626370987794816660694178305939474922064726534186386488052827919792122844587807300048430756990391177266977583227470089929347969731703368720788359127837289988944365786283419724178187242169399457608505627145016468888402441344333481249304670223
e = 11079917583
c = 13354219204055754230025847310134936965811370208880054443449019813095522768684299807719787421318648141224402269593016895821181312342830493800652737679627324687428327297369122017160142465940412477792023917546122283870042482432790385644640286392037986185997262289003477817675380787176650410819568815448960281666117602590863047680652856789877783422272330706693947399620261349458556870056095723068536573904350085124198592111773470010262148170379730937529246069218004969402885134027857991552224816835834207152308645148250837667184968030600819179396545349582556181916861808402629154688779221034610013350165801919342549766

s = 120561
t = 91903


ab = int(gmpy2.iroot(n,4)[0])

# var('a b')
# f1 = a*b-ab
# f2 = ab^4 + a^4*t + b^4*s + s*t - n
# ans = solve([f1,f2],[a,b])
# print(ans)

a = 47783641287938625512681830427927501009821495321018170621907812035456872958654
b = 44416071018427916652440592614276227563515579156219730344722242565477265479486

p = a^4 + s
q = b^4 + t
assert p*q == n

phi = (p-1)*(q-1)

# print(gcd(e,phi))
# 21

d = gmpy2.invert(e // 21,p - 1)
m_21 = pow(c,d,p)
#求出m的21次方
e = 21

R.<x>=PolynomialRing(Zmod(p))
f = x^e - m_21
f = f.monic()
mps = f.roots()
for i in mps:
    flag=long_to_bytes(int(i[0]))
    if b'DASCTF' in flag:
        print(flag)

一般flag没有填充的情况下,会小于p,所以用 p , q p,q p,q单独作公钥求解

求解出 m 21 ≡ c d m o d    p m^{21} \equiv c^{d} \mod p m21cdmodp

再用多项式环求根

参考:2023 CryptoCTF wp by lingfeng (medium分类——1)_c_ling_feng的博客-CSDN博客

Easy_3L

题目:

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

m = bytes_to_long(flag)


def get_key():
    p = getPrime(1400)
    f = getRandomNBitInteger(1024)
    while True:
        q = getPrime(512)
        if gcd(f, q) != 1:
            continue
        else:
            break
    h = (invert(f, p) * q) % p
    return p, h


def encrypt1(m):
    a = getPrime(250)
    b = getRandomNBitInteger(240)
    n = getPrime(512)
    seed = m
    s = [0] * 6
    s[0] = seed
    for i in range(1, 6):
        s[i] = (s[i - 1] * a + b) % n
    return s


def encrypt2(msg, p, h):
    s = getRandomNBitInteger(512)
    c = (s * h + msg) % p
    return c


s = encrypt1(m)
print("S1 =", s[1])
print("S2 =", s[2])
print("S4 =", s[4])
print("S5 =", s[5])

p, h = get_key()
c = encrypt2(s[3], p, h)
print("p =", p)
print("h =", h)
print("c =", c)

# S1 = 
# S2 = 
# S4 = 
# S5 = 
# p = 
# h = 
# c = 

没给出S3,要先把S3求出来,然后就是LCG求解

已知 c ≡ s h + m s g m o d    p ⟶ c = s h + m s g + k p c \equiv sh+msg \mod p \longrightarrow c = sh + msg +kp csh+msgmodpc=sh+msg+kp

∴ m s g = c − s h − k p \therefore msg = c - sh -kp msg=cshkp

构造这样的格

在这里插入图片描述

exp:

#sage
from Crypto.Util.number import *
import gmpy2

p = 25886434964719448194352673440525701654705794467884891063997131230558866479588298264578120588832128279435501897537203249743883076992668855905005985050222145380285378634993563571078034923112985724204131887907198503097115380966366598622251191576354831935118147880783949022370177789175320661630501595157946150891275992785113199863734714343650596491139321990230671901990010723398037081693145723605154355325074739107535905777351
h = 2332673914418001018316159191702497430320194762477685969994411366563846498561222483921873160125818295447435796015251682805613716554577537183122368080760105458908517619529332931042168173262127728892648742025494771751133664547888267249802368767396121189473647263861691578834674578112521646941677994097088669110583465311980605508259404858000937372665500663077299603396786862387710064061811000146453852819607311367850587534711
c = 20329058681057003355767546524327270876901063126285410163862577312957425318547938475645814390088863577141554443432653658287774537679738768993301095388221262144278253212238975358868925761055407920504398004143126310247822585095611305912801250788531962681592054588938446210412897150782558115114462054815460318533279921722893020563472010279486838372516063331845966834180751724227249589463408168677246991839581459878242111459287

Ge = Matrix(ZZ,[
    [-p,0,0],
    [-h,1,0],
    [c,0,2^512]
])

for i in Ge.LLL():
    if abs(i[-1]) == 2^512:
        S3 = i[0]

S1 = 28572152986082018877402362001567466234043851789360735202177142484311397443337910028526704343260845684960897697228636991096551426116049875141
S2 = 1267231041216362976881495706209012999926322160351147349200659893781191687605978675590209327810284956626443266982499935032073788984220619657447889609681888
S4 = 9739918644806242673966205531575183334306589742344399829232076845951304871478438938119813187502023845332528267974698273405630514228632721928260463654612997
S5 = 9755668823764800147393276745829186812540710004256163127825800861195296361046987938775181398489372822667854079119037446327498475937494635853074634666112736

output = [S1,S2,S3,S4,S5]
t = []
for i in range(1,len(output)):
    t.append(output[i]-output[i-1])

T = []
for i in range(1,len(t)-1):
    T.append(t[i+1]*t[i-1] - t[i]**2)

m = []
for i in range(len(T)-1):
    mm = gmpy2.gcd(T[i],T[i+1])
    m.append(int(mm))
# print(m)
for i in m:
    if isPrime(i):
        a = gmpy2.invert(t[0],i) * t[1] % i
        b = output[1] - a*output[0] % i
        a_ = gmpy2.invert(a,i)

        seed = a_ * (output[0]-b) % i
        print(long_to_bytes(seed))

signinCrypto

from random import *
from Crypto.Util.number import *
from Crypto.Cipher import DES3
from flag import flag
from key import key
from iv import iv
import os
import hashlib
import secrets

K1= key
hint1 = os.urandom(2) * 8
xor =bytes_to_long(hint1)^bytes_to_long(K1)
print(xor)

def Rand():
    rseed = secrets.randbits(1024)
    List1 = []
    List2 = []
    seed(rseed)
    for i in range(624):
        rand16 = getrandbits(16)
        List1.append(rand16)
    seed(rseed)
    for i in range(312):
        rand64 = getrandbits(64)
        List2.append(rand64)
    with open("task.txt", "w") as file:
        for rand16 in List1:
            file.write(hex(rand16)+ "\n")
        for rand64 in List2:
            file.write(hex((rand64 & 0xffff) | ((rand64 >> 32) & 0xffff) << 16) + "\n")
Rand()

K2 = long_to_bytes(getrandbits(64))
K3 = flag[:8]

KEY = K1 + K2 + K3

IV=iv

IV1=IV[:len(IV)//2]
IV2=IV[len(IV)//2:]

digest1 = hashlib.sha512(IV1).digest().hex()
digest2 = hashlib.sha512(IV2).digest().hex()

digest=digest1+digest2
hint2=(bytes_to_long(IV)<<32)^bytes_to_long(os.urandom(8))
print(hex(bytes_to_long((digest.encode()))))
print(hint2)


mode = DES3.MODE_CBC
des3 = DES3.new(KEY, mode, IV)

pad_len = 8 - len(flag) % 8
padding = bytes([pad_len]) * pad_len
flag += padding

cipher = des3.encrypt(flag)

ciphertext=cipher.hex()
print(ciphertext)

# 334648638865560142973669981316964458403
# 0x62343937373634656339396239663236643437363738396663393438316230353665353733303939613830616662663633326463626431643139323130616333363363326631363235313661656632636265396134336361623833636165373964343533666537663934646239396462323666316236396232303539336438336234393737363465633939623966323664343736373839666339343831623035366535373330393961383061666266363332646362643164313932313061633336336332663136323531366165663263626539613433636162383363616537396434353366653766393464623939646232366631623639623230353933643833
# 22078953819177294945130027344
# a6546bd93bced0a8533a5039545a54d1fee647007df106612ba643ffae850e201e711f6e193f15d2124ab23b250bd6e1

重点是求KEYIV

观察代码,能猜测出,K1IV,长度为8,

说明xor =bytes_to_long(hint1)^bytes_to_long(K1),hint1的高位没有受影响

输出long_to_bytes(xor),能够得到hint1 = b'\xfb\xc2' * 8

随即能出K1 = b"dasctfda"

K2通过随机数求得

给出的是rand64[16:32]+rand64[48:64]

随机数的生成机制: 通过生成32bit的数进行拼接或者移位(大佬教的)

如果要生成16bit的数,是先生成32bit再取这个数的高16位

如果要生成64bit的数,先生成两个32bit的数x1,x2,再进行拼接x2||x1

本题中,因为两次seed是一样的,所以rand16就是x1的前16位,后面输出的rand16x2的前16位

rand64 = x2[:16] || rand64[16:32] || x1[:16] || rand64[48:64]

这样就有了全部rand64,一共312个rand64

K3前七位是DASCTF{,最后一位不太确定

又因为hint2=(bytes_to_long(IV)<<32)^bytes_to_long(os.urandom(8)),说明IV的前面32bit不受影响

直接打印出,得到b'GWHT',注意到给出的那一段数据是两端重复数据拼接在一起的。

说明IV1 = IV2 = b'GWHT' ∴ \therefore IV = b'GWHTGWHT'

exp:

from Crypto.Util.number import *
from Crypto.Cipher import DES3
from extend_mt19937_predictor import ExtendMT19937Predictor

predictor = ExtendMT19937Predictor()

xor = 334648638865560142973669981316964458403
# print(long_to_bytes(xor))

hint1 = b'\xfb\xc2' * 8

K1 = long_to_bytes(bytes_to_long(hint1) ^ xor)
# print(K1)
# K1 = b'dasctfda'
hint2 = 22078953819177294945130027344
# print(long_to_bytes(hint2))

K1 = b"dasctfda"
IV = b"GWHTGWHT"

f = open("task.txt",'r')

data = []
for i in f.readlines():
    data.append(eval(i))

data1 = data[:624]
data2 = data[624:]

data3 = []

for i in data2:
    b = (i >> 16) & 0xffff
    d = i & 0xffff
    data3.append(d)
    data3.append(b)
for i,j in zip(data1,data3):
    t = (i << 16) + j
    predictor.setrandbits(t,32)

K2 = long_to_bytes(predictor.predict_getrandbits(64))
# print(K2)
K3 = b"DASCTF{"

c = "a6546bd93bced0a8533a5039545a54d1fee647007df106612ba643ffae850e201e711f6e193f15d2124ab23b250bd6e1"
c = bytes.fromhex(c)
for i in range(2**8):
    KEY = K1 + K2 + K3 + long_to_bytes(i)
    try:
        mode = DES3.MODE_CBC
        des3 = DES3.new(KEY, mode, IV)
        flag = des3.decrypt(c)
        if b'DASCTF{' in flag:
            print(flag)
    except:
        continue

esyRSA——复现

from gmpy2 import invert
from md5 import md5
from secret import p, q

e = ?????
n = p*q
phi = (p-1)*(q-1)
d = invert(e, phi)
ans = gcd(e,phi)

print n, e, d
print "Flag: DASCTF{%s}" %md5(str(p + q)).hexdigest()

"""
n = 
d = 14218766449983537783699024084862960813708451888387858392014856544340557703876299258990323621963898510226357248200187173211121827541826897886277531706124228848229095880229718049075745233893843373402201077890407507625110061976931591596708901741146750809962128820611844426759462132623616118530705745098783140913
"""

发现这个n是有重复部分的,把重复部分删去后是正确的n

n=80642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373

∵ e d ≡ 1 m o d    ϕ ( n ) \because ed \equiv 1 \mod \phi(n) ed1modϕ(n)

$\longrightarrow ed = k\phi(n) + 1\$

同除 e × ϕ ( n ) e \times \phi(n) e×ϕ(n)

⟶ d ϕ ( n ) = k e + 1 e × ϕ ( n ) \longrightarrow \frac{d}{\phi(n)} = \frac{k}{e} + \frac{1}{e\times \phi(n)} ϕ(n)d=ek+e×ϕ(n)1

∵ ϕ ( n ) ≈ n \because \phi(n) \approx n ϕ(n)n

∴ 上式 ⟶ d n ≈ k e \therefore 上式 \longrightarrow \frac{d}{n} \approx \frac{k}{e} 上式ndek

d n \frac{d}{n} nd进行连分数展开,得到的一串分数的分母很可能就是e

exp:

#sage
import hashlib

n = 80642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373
d = 14218766449983537783699024084862960813708451888387858392014856544340557703876299258990323621963898510226357248200187173211121827541826897886277531706124228848229095880229718049075745233893843373402201077890407507625110061976931591596708901741146750809962128820611844426759462132623616118530705745098783140913

c = continued_fraction(Integer(d) / Integer(n))

i = 1
while 1:
    k = int(c.numerator(i))       #取连分数的分子
    e = int(c.denominator(i))     #取连分数的分母
    #计算kphi
    if (e * d - 1) % k == 0 and len(str(e)) == 5:
        phi = (e * d - 1) // k
        p_q = n - phi + 1
        print("p+q=",p_q)
        print("e=",e)
        # e = 13521
        print("k=",k)
        # k = 2384
        var('p q')
        f1 = p * q - n
        f2 = p + q - p_q
        sol = solve([f1,f2],[p,q])
        print(sol)
        break
    else:
        i += 1

p = 7920625690369490250766357750388349704260128405941822835255851274284409978206593795103040446837018619894098452542488850045009467407103749792461438242280929
q = 10181341212828413853336916619161138854377885230386496425058202154486415709366161346816273366144505351043947477469664133317598479763451392984403646602585037

flag = "DASCTF{" + hashlib.md5(str(p+q).encode()).hexdigest() + '}'
print(flag)

另外一种用格的思路解决

∵ e d ≡ 1 m o d    p h i \because ed \equiv 1 \mod phi ed1modphi

∴ e d = k p h i + 1 ⟶ e d = k ( n − p − q + 1 ) + 1 \therefore ed = kphi + 1 \longrightarrow ed = k(n - p - q + 1) + 1 ed=kphi+1ed=k(npq+1)+1

e d = k n − k ( p + q − 1 ) + 1 ed = kn - k(p+q-1)+1 ed=knk(p+q1)+1

k ( p + q − 1 ) − 1 = k n − e d k(p+q-1)-1 = kn -ed k(p+q1)1=kned

构造格
在这里插入图片描述

规约后能得到e,再求k(p+q-1)ed - 1的公因数得到k

exp:

import hashlib

n = 80642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373
d = 14218766449983537783699024084862960813708451888387858392014856544340557703876299258990323621963898510226357248200187173211121827541826897886277531706124228848229095880229718049075745233893843373402201077890407507625110061976931591596708901741146750809962128820611844426759462132623616118530705745098783140913

Ge = Matrix(ZZ,[
    [2^512 , d],
    [0 , n]]
    )

L = Ge.LLL()[0]
e = abs(L[0]) // 2^512

k = gcd(e*d - 1,L[1]+1)

p_q = (L[1]+1) // k + 1
flag = "DASCTF{" + hashlib.md5(str(p_q).encode()).hexdigest() + '}'
print(flag)

MCeorpkpleer

题目:

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


def pubkey(list, m, w):
    pubkey_list = []
    for i in range(len(e_bin)):
        pubkey_list.append(w * list[i] % m)
    return pubkey_list


def e_cry(e, pubkey):
    pubkey_list = pubkey
    encode = 0
    for i in range(len(e)):
        encode += pubkey_list[i] * int(e[i]) % m
    return encode


p = getPrime(1024)
q = getPrime(1024)
n = p * q
e = getPrime(64)
m = bytes_to_long(flag)
c = pow(m, e, n)

e_bin = (bin(e))[2:]
list = [pow(3, i) for i in range(len(e_bin))]
m = getPrime(len(bin(sum(list))) - 1)
w = getPrime(64)
pubkey = pubkey(list, m, w)
en_e = e_cry(e_bin, pubkey)

print('p = {}\n'
      'n = {}\n'
      'c = {}\n'
      'pubkey = {}\n'
      'en_e = {}'.format((p >> 435) << 435, n, c, pubkey, en_e))

'''
p = 
n = 
c = 
pubkey = 
en_e = 31087054322877663244023458448558
'''

给出p的高位,coppersmith梭出p

需要求一下e

观察加密发现,list是固定的,因为len(e_bin)==64

而且pubkey的第一位就是w

∵ p u b k e y i ≡ l i s t i × w m o d    m \because pubkey_i \equiv list_i × w \mod m pubkeyilisti×wmodm

∴ k m = l i s t i × w − p u b k e y i \therefore km = list_i \times w-pubkey_i km=listi×wpubkeyi

通过这个,求出几个km,再求公因数,经过验证即可求得m = 4522492601441914729446821257037

然后感觉是解背包加密$c = (pubkey_1×e_1 \mod m) + \dots + (pubkey_{64}×e_{64}\mod m) $

构造格
( 1 0 0 … 0 0 k e y 1 0 1 0 … 0 0 k e y 2 0 0 1 … 0 0 k e y 3 ⋮ ⋮ ⋮ ⋱ ⋮ ⋮ ⋮ 0 0 0 … 1 0 k e y 64 0 0 0 … 0 1 c 0 0 0 … 0 0 p ) \begin{pmatrix} 1 & 0 & 0 & \dots & 0 & 0 & key_1\\ 0 & 1 & 0 & \dots & 0 & 0 & key_2\\ 0 & 0 & 1 & \dots & 0 & 0 & key_3\\ \vdots & \vdots & \vdots & \ddots & \vdots & \vdots & \vdots\\ 0 & 0 & 0 & \dots & 1 & 0& key_{64}\\ 0 & 0 & 0 & \dots & 0 & 1 & c\\ 0 & 0 & 0 & \dots & 0 & 0 & p \end{pmatrix} 100000010000001000000100000010key1key2key3key64cp
正确结果卡在中间,一开始没发现,以为是自己思路错了。草!!!!!!

exp:

from Crypto.Util.number import *
import gmpy2

phigh = 
N = 
enc = 


R.<x> = PolynomialRing(Zmod(n))

f = phigh + x
root = f.small_roots(X = 2^435,beta = 0.4)
if root:
    p = phigh + int(root[0])
# print(p)
    q = N // p
    
mod = 
pubkey = 
c = 

n = len(pubkey)

Ge = Matrix(ZZ,n+2,n+2)
for i in range(n):
    Ge[i,i] = 1
    Ge[i,-1] = pubkey[i]

Ge[-2,-2] = 1
Ge[-2,-1] = c
Ge[-1,-1] = mod


for i in Ge.LLL():
    if i[-1] == 0:
        tmp = i[:-2]
        ans = ''
        for j in tmp:
            if abs(j) == 0:
                ans += '0'
            if abs(j) == 1:
                ans += '1'
        e = int(ans,2)
        if isPrime(e) and e.bit_length() == 64:
            print(e)
            d = gmpy2.invert(e,(p-1)*(q-1))
            m = pow(enc,d,N)
            print(long_to_bytes(int(m)))

下次一定看清楚www

另外一种解法是利用上超递增序列list

∵ c = ( p u b k e y 1 × e 1 m o d    m ) + ⋯ + ( p u b k e y 64 × e 64 m o d    m ) \because c = (pubkey_1×e_1 \mod m) + \dots + (pubkey_{64}×e_{64}\mod m) c=(pubkey1×e1modm)++(pubkey64×e64modm)

p u b k e y ≡ w × l i s t pubkey \equiv w \times list pubkeyw×list代入

∴ c = ( w × l i s t 1 × e 1 m o d    m ) + ⋯ + ( w × l i s t 64 × e 64 m o d    m ) \therefore c = (w \times list_1 \times e_1 \mod m) + \dots + (w \times list_{64} \times e_{64} \mod m) c=(w×list1×e1modm)++(w×list64×e64modm)

∴ c ≡ w ( l i s t 1 × e 1 + ⋯ + l i s t 64 × e 64 ) m o d    m \therefore c \equiv w(list_1 \times e_1 + \dots +list_{64}\times e_{64} ) \mod m cw(list1×e1++list64×e64)modm

c × w − 1 ≡ l i s t 1 × e 1 + ⋯ + l i s t 64 × e 64 m o d    m c \times w^{-1} \equiv list_1 \times e_1 + \dots +list_{64}\times e_{64} \mod m c×w1list1×e1++list64×e64modm

list是个超递增序列

exp:

from Crypto.Util.number import *

c = 31087054322877663244023458448558
mod = 4522492601441914729446821257037
w = 18143710780782459577

c = c * inverse(w,mod) % mod

list1 = [pow(3, i) for i in range(64)]

m = ''
for i in list1[::-1]:
    if c >= i:
        m += '1'
        c -= i
    else:
        m += '0'
        
e = int(m[::-1],2)
print(e)
# e =15960663600754919507

XOR贯穿始终

先核心价值观解码得到压缩包的密钥:C0ngr4tulati0n5_y0u_fou^d_m3

拿到题目,以及私钥文件

from gmpy2 import gcd
from Crypto.Util.number import getPrime
from secret import enflag

p = getPrime(512)
q = getPrime(512)
n = q * p
phi = (p - 1) * (q - 1)
e = getPrime(17)
assert gcd(e, phi) == 1
# 以上信息生成了私钥文件,但文件被损坏了你能提取有用信息吗

c = pow(enflag, e, n)
print('c = ' + str(c))

'''
c = 91817924748361493215143897386603397612753451291462468066632608541316135642691873237492166541761504834463859351830616117238028454453831120079998631107520871612398404926417683282285787231775479511469825932022611941912754602165499500350038397852503264709127650106856760043956604644700201911063515109074933378818
'''
-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALmtMy+2uH1ZtbIL
SuiAukFthyQRH5mp7UmLyzZQkdg9zEP9/5tgffikQ7ytx5kHySHnazgAO1sOzmYE
N4Axlev6uafiP8B1Eij97v5VkYJ1I9e3mtBNheTbXKoT8op+ASQ1fQaF4A8UzLuW
eZeZI8JTH/SH+bolAK3kiZXDFdkTAgMBAAECgYEAl067LaC7Cvs2A5cMPhfYsESv
IgcKN1CwW4Sd3u8dSphhgu7TgyzIuvwxbuo2g1BC6WwKhaI6vGN+csfw6nh98GEn
/p3D0huNroAYvf/DRRB9UnHdttX7wB+Mv3P0RBDWHgBiCDVvHFuFUV78cIs0tnbn
jxjU07aPV2XRC3AfA2ECQQDqWUNPVg3i6vTyHCL7EGkbeUheYpAAfcKCQrxjc5+5
X6A+XtgHAA1JHwykPlCpHUOmlA85DJF1ejuoImzlgRLJAkEAytTCnQF+MN2r1gaA
UETZyj5qMYT7Th8zKEVVVJjDawLnuX4usJ2FyRnjCkk86U75QSJhw5mMc0QnG25u
Gz3++w==
-----END PRIVATE KEY-----

私钥文件base64解密再转16进制

根据(PKCS1) RSA 公私钥 pem 文件解析 - 知乎 (zhihu.com)

在这里插入图片描述

提取到n,p,q。然后解密。中间那段绿色的不太明白代表什么意思,求师傅教教。后面了解到那个是d

解出来的结果和压缩包密钥异或一下才是真的flag。当时想到异或,但是把字符拿来异或了,卡了几分钟才做出来的导致痛失三血www

exp:

from Crypto.Util.number import *
import gmpy2

n = 0xb9ad332fb6b87d59b5b20b4ae880ba416d8724111f99a9ed498bcb365091d83dcc43fdff9b607df8a443bcadc79907c921e76b38003b5b0ece660437803195ebfab9a7e23fc0751228fdeefe5591827523d7b79ad04d85e4db5caa13f28a7e0124357d0685e00f14ccbb9679979923c2531ff487f9ba2500ade48995c315d913
e = 0x10001
p = 0xcad4c29d017e30ddabd606805044d9ca3e6a3184fb4e1f332845555498c36b02e7b97e2eb09d85c919e30a493ce94ef9412261c3998c7344271b6e6e1b3dfefb
q = 0xea59434f560de2eaf4f21c22fb10691b79485e6290007dc28242bc63739fb95fa03e5ed807000d491f0ca43e50a91d43a6940f390c91757a3ba8226ce58112c9

c = 91817924748361493215143897386603397612753451291462468066632608541316135642691873237492166541761504834463859351830616117238028454453831120079998631107520871612398404926417683282285787231775479511469825932022611941912754602165499500350038397852503264709127650106856760043956604644700201911063515109074933378818

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

a = b'C0ngr4tulati0n5_y0u_fou^d_m3'
flag = long_to_bytes(bytes_to_long(a) ^ int(m))
print(flag)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值