BuildCTF2024-Crypto
差一题古典不想看了,其他方向就不献丑了
Crypto
OVO开门爽!开到南天门了兄弟
from Crypto.Util.number import *
flag = b'BuildCTF{******}'
#随机生成p,q
p = getPrime(1024)
q = getPrime(1024)
#计算模数n
n = p*q
e = 65537
m = bytes_to_long(flag)
#c=m^e%n
c = pow(m, e, n)
print('P = ',p**2)
print('Q = ',q**2)
print('n = ',n)
print('e = ',e)
print('c = ',c)
开根就行了
from Crypto.Util.number import *
from gmpy2 import *
P = 8279853330757234669136483032750824826175777927506575083710166412897012079466955769715275604152872242147320194640165649152928984919315754419447729793483984130396358578571137956571302516202649076619076831997922675572705848199504309232044502957866317011212505985284129365522570368395368427388904223782742850616983130885152785650513046301920305069822348366931825404271695876688539675285303882189060671184911139742554710018755565518014777733322795522710234091353878298486498244829638878949389690384488573338138825642381687749888102341379254137445546306796258092762099409409285871651688611387507673794784257901946892698481
Q = 9406643503176766688113904226702477322706664731714272632525763533395380298320140341860043591350428258361089106233876240175767826293976534568274153276542755524620138714767338820334748140365080856474253334033236457092764244994983837914955286808153784628739327217539701134939748313123071347697827279169952810727995681780717719971161661561936180553161888359929479143712061627854343656949334882218260141557768868222151468471946884225370009706900640851492798538458384449294042930831359723799893581568677433868531699360789800449077751798535497117004059734670912829358793175346866262442550715622833013235677926312075950550681
n = 8825283482190476005946253343638820879559355306860912268128891241513310054066424567824202757539757712177309282694997613217968336164050770152277369601415394249781577415456224120102543968285035647514461364611734338073523454354376992783551035395558194171202680855182868766563277697325690226849316944101739491659812174054898519492145495098671439125714086449826697343692081109131564556220174583970363431110462222473013021825770267803249515893736989430146194199936335153936611196467225599746830873958085287665223190767137404366840055297859554490123389877396965710177279558954630222879974581602069901175074777191362537419581
e = 65537
c = 27915082942179758159664000908789091022294710566838766903802097394437507062054409033932303966820096232375646873480427485844733381298467171069985418237873120984132166343258345389477844339261488318588760125230979340678006871754125487279212120945061845738130108370814509280317816067243605608952074687396728904772649873860508240809541545939219624254878900291126739390967820141036260712208555574522131446556595562330969209665291757386246648060990840787769772160549862538116370905306402293764494501838709895355570646716245976733542014165663539815972755562821443411642647981898636761822107221203966296758350547477576411216744594534002057673625678188824476543288048956124565509473100550838563085585434675727358831610724920550213350035792170323729397796947598697983084347567191009236345815968927729025919066227704728180060805553787151862426034275526605154807840695498644070184681962311639338273469859838505348823417234722270798882384367058630064108155240680307754557472476430983184039474907188578578484589833812196216551783354411797156409948499012005963943728564803898150155735762695825658678475746559900705796814512838380193603178657226033406812810314960142251012223576984115642351463684724512456778548853002653596485899854303126091917273560
p=int(iroot(P,2)[0])
q=int(iroot(Q,2)[0])
print(long_to_bytes(int(pow(c,invert(e,(p-1)*(q-1)),p*q))))
mitm
from Crypto.Util.number import *
from Crypto.Util.Padding import *
from hashlib import sha256
from Crypto.Cipher import AES
from random import *
from secret import flag
note = b'Crypt_AES*42$@'
r = 4
keys = []
for i in range(r):
key = bytes(choices(note, k=3))
keys.append(sha256(key).digest())
leak = b'Hello_BuildCTF!!'
cipher = leak
for i in range(r):
cipher = AES.new(keys[i], AES.MODE_ECB).encrypt(cipher)
enc_key = sha256(b"".join(keys)).digest()
enc_flag = AES.new(enc_key, AES.MODE_ECB).encrypt(pad(flag, AES.block_size))
print(f'cipher = {cipher}')
print(f'enc_flag = {enc_flag}')
前段之前遇到过,就想出来了
参考的是小鸡块师傅的
crewCTF-4ES:2024-TFCCTF&crewCTF-wp-crypto | 糖醋小鸡块的blog (tangcuxiaojikuai.xyz)
from hashlib import sha256
from Crypto.Cipher import AES
import itertools
cipher = b'\xb9q\x04\xa3<\xf0\x11-\xe9\xfbo:\x9aQn\x81'
enc_flag = b'q\xcf\x08$%\xb0\x86\xee\x1a(b\x7f\xf8\x86\xbd\xd0\xa7\xee\xd9\x9d2\x82a7H=a\x13\x87e\xad\xd2b\x8e\x07\xa5\xddo\xc0\xf3N\xd4b\xc9o\x88$\xc7\xf4p\xc1\x1e,\xed\xcc\x94\x8c\xf4\x00\xa5\xe0-\xf7\xc5'
note = b'Crypt_AES*42$@'
leak = b'Hello_BuildCTF!!'
keys=[]
for key in itertools.product(note, repeat=3):
keys.append(sha256(bytes(key)).digest())
print("over0")
pre={}
for key in itertools.product(keys, repeat=2):
pre[AES.new(key[1], AES.MODE_ECB).encrypt(AES.new(key[0], AES.MODE_ECB).encrypt(leak))]=key
print("over1")
for key in itertools.product(keys, repeat=2):
if AES.new(key[1], AES.MODE_ECB).decrypt(AES.new(key[0], AES.MODE_ECB).decrypt(cipher)) in pre.keys():
pre_key=pre[AES.new(key[1], AES.MODE_ECB).decrypt(AES.new(key[0], AES.MODE_ECB).decrypt(cipher))]
tmp=pre_key[0]+pre_key[1]+key[1]+key[0]
keys=sha256(tmp).digest()
flag = AES.new(keys, AES.MODE_ECB).decrypt(enc_flag)
print(flag)
exit()
#b'BuildCTF{M1tm_i5_@_simple_w@y_t0_s0lve_pr0bl3m!}\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10'
我这辈子就是被古典给害了
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
from Crypto.Cipher import AES
from secret import flag, key
dict1 = {'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4,
'F': 5, 'G': 6, 'H': 7, 'I': 8, 'J': 9,
'K': 10, 'L': 11, 'M': 12, 'N': 13, 'O': 14,
'P': 15, 'Q': 16, 'R': 17, 'S': 18, 'T': 19,
'U': 20, 'V': 21, 'W': 22, 'X': 23, 'Y': 24, 'Z': 25}
dict2 = {0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E',
5: 'F', 6: 'G', 7: 'H', 8: 'I', 9: 'J',
10: 'K', 11: 'L', 12: 'M', 13: 'N', 14: 'O',
15: 'P', 16: 'Q', 17: 'R', 18: 'S', 19: 'T',
20: 'U', 21: 'V', 22: 'W', 23: 'X', 24: 'Y', 25: 'Z'}
def generate_key(flag, key):
i = 0
while True:
if len(key) == len(flag):
break
key += flag[i]
i += 1
return key
def cipherText(msg, key_new):
cipher_text = ''
i = 0
for letter in msg:
x = (dict1[letter] + dict1[key_new[i]]) % 26
i += 1
cipher_text += dict2[x]
return cipher_text
def AES_enc(key, value):
key = (key * 2).encode()
cipher = AES.new(key, AES.MODE_ECB)
value = value.encode()
padded_text = pad(value, AES.block_size)
ciphertext = cipher.encrypt(padded_text)
print("AES Encrypted Text =", ciphertext)
def substitute(msg):
msg = msg.replace('{', 'X')
msg = msg.replace('_', 'X')
msg = msg.replace('}', 'X')
msg = msg.upper()
assert msg.isupper()
return msg
message = substitute(flag)
key_new = generate_key(message, key)
cipher = cipherText(message, key_new)
print("Encrypted Text =", cipher)
AES_enc(key, flag)
讲解写在代码里了
dict1 = {'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4,
'F': 5, 'G': 6, 'H': 7, 'I': 8, 'J': 9,
'K': 10, 'L': 11, 'M': 12, 'N': 13, 'O': 14,
'P': 15, 'Q': 16, 'R': 17, 'S': 18, 'T': 19,
'U': 20, 'V': 21, 'W': 22, 'X': 23, 'Y': 24, 'Z': 25}
dict2 = {0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E',
5: 'F', 6: 'G', 7: 'H', 8: 'I', 9: 'J',
10: 'K', 11: 'L', 12: 'M', 13: 'N', 14: 'O',
15: 'P', 16: 'Q', 17: 'R', 18: 'S', 19: 'T',
20: 'U', 21: 'V', 22: 'W', 23: 'X', 24: 'Y', 25: 'Z'}
text = "HLMPWKGLYSWFACEWBYRSUKYFAXZFXDKOTZHHSLFCXNICAHPGRIFUF"
# len(AES_KEY)=16 24 32
# len(key)=8 12 16
# 假设key一开始长度为8,flag头猜测为BUILDCTFX
# 则key=????????BUILDCTFX
# 密文第9位,就等于现在key第九位'X' 加上 flag第一位'B'
# print(dict1[text[8]]) 24
# 23+1=24 ==> X+B 所以可以猜测一开始key长度为8
pre="BUILDCTF"
key=""
for i in range(8):
key+=dict2[(dict1[text[i]]-dict1[pre[i]])%26]
# print(key) # 结果为:GREETING,有明显英文意思,推论正确
from Crypto.Cipher import AES
c = b'\x92T{\x1f\x0f"\xbd\xbb\xfa|O\x11\x83\xa0\xec.\x15]\x9f\x9a\xe5\x85Z\x9f@yUm\xbb\xdc\x93\x08\xe5\x8b\xd5\x98\x84\xfa\x91\xe8\xde\x1b}\xcd\x9056\xa3\xbf\xdb\x85J\xcc\xec\x812T\x11\xa7Tl\x15\xf6"'
key=key*2
cipher = AES.new(key.encode(), AES.MODE_ECB)
ciphertext = cipher.decrypt(c)
print(ciphertext)
#b'BuildCTF{YOU_ALREADY_KNOW_WHAT_A_CLASSICAL_CIPHER_IS}\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b'
gift
from Crypto.Util.number import *
from secret import flag
def get_gift(p, q):
noise = getPrime(40)
p, q = p + 2 * noise + 1, q - pow(noise, 2)
gift = 2024 * (p + q)
return gift
p = getPrime(512)
q = getPrime(512)
n = p * q
e = 0x10001
m = bytes_to_long(flag)
c = pow(m, e, n)
gift = get_gift(p, q)
print(f'c = {c}')
print(f'n = {n}')
print(f'gift = {gift}')
'''
c = 101383046356447336426623798470530695448361708798731382238747567108067236241251384089401506320741815081024352908156466877907424203888923965647318146770258139921360377246187637085549628797640957048672797430217647039035455011311505942632107576730906489223641894279483592789523228409885925263914621255862261546919
n = 131097719698687108485813302886652389604731026998272796315024695395496199386497660846418712521921387496051077394308820230360184411431376692252923609505060476542577219656866593501271690536991944882324175509626138475159461332403161471880082192150081456601522403673111515117219716055561941951891570977025178643791
gift = 46635322848619790584491725916282901439691751328335921415278638528896063068132242718070261114525516272650970256270551306096774004921902972838212903368063625872
'''
不愧是noise,noise40位,平方之后差不多80位,p和q都是512位的,相加之后可以相当于丢失了低80位,所以就想到是p+q的高位攻击。
我直接偷dexter师傅的代码了
https://dexterjie.github.io/2023/09/07/挨打日记/#2023长城杯——p-q高位泄露
N = 131097719698687108485813302886652389604731026998272796315024695395496199386497660846418712521921387496051077394308820230360184411431376692252923609505060476542577219656866593501271690536991944882324175509626138475159461332403161471880082192150081456601522403673111515117219716055561941951891570977025178643791
gift = 46635322848619790584491725916282901439691751328335921415278638528896063068132242718070261114525516272650970256270551306096774004921902972838212903368063625872
gift=gift//2024
gift=gift>>90
gift=gift<<90
PR.<x> = PolynomialRing(Zmod(N))
ok = False
test=1
def pq_add(tp,tq,tgift,idx):
global ok
global test
if ok:
return
if tp*tq>N:
#print('>')
return
if (tp+(2<<idx))*(tq+(2<<idx))<N:
#print('<', hex((tp+(1<<(idx+2))))[:20], hex(tq+(2<<idx))[:20], hex(N)[:20])
return
if idx<=90:
try:
test += 1
print(test)
for i in range(1024):
tpp = tp+(i<<90)
f = tpp + x
test += 1
rr = f.monic().small_roots(X=2^90, beta=0.4)
if rr != []:
print(rr)
print(tpp)
print('p = ',f(rr[0]))
ok = True
return
except:
pass
return
idx -=1
b = tgift >>idx
one = 1<<idx
#print(hex(tp)[:20],hex(tq)[:20],hex(tgift)[:20],idx,b)
if b==0 or b==1:
pq_add(tp,tq,tgift,idx)
if b==1 or b==2:
pq_add(tp+one,tq,tgift-one,idx)
pq_add(tp,tq+one,tgift-one,idx)
if b==2 or b==3:
pq_add(tp+one,tq+one,tgift-(one<<1),idx)
if 0:
tp = 1<<511
tq = 1<<511
tgift = gift -tp -tq
pq_add(tp,tq,tgift,511)
"""
print(test)
print("OK")
print("111111111111")
17427
[700928575142400370721495237]
12795781443930923314957498667934210380943999998587811382302993343213015802362418444051944067150691108651897157419444913377465524852577234852023651836887040
p = 12795781443930923314957498667934210380943999998587811382302993343213015802362418444051944067150691108651897157419444913377465525553505809994424022558382277
17432
OK
111111111111
"""
from Crypto.Util.number import *
p = 12795781443930923314957498667934210380943999998587811382302993343213015802362418444051944067150691108651897157419444913377465525553505809994424022558382277
c = 101383046356447336426623798470530695448361708798731382238747567108067236241251384089401506320741815081024352908156466877907424203888923965647318146770258139921360377246187637085549628797640957048672797430217647039035455011311505942632107576730906489223641894279483592789523228409885925263914621255862261546919
print(long_to_bytes(int(pow(c,inverse_mod(65537,p-1),p))))
# b'BuildCTF{M@y_b3_S0m3th1ng_go_wr0ng}'
ominous
from Crypto.Util.number import *
from secret import flag
import random
import string
Ominous_dic = ['啊', '米', '诺', '斯']
flag_word = (string.ascii_letters + string.digits + '{}@_!').encode()
assert all(char in flag_word for char in flag)
msg = bytes_to_long(flag)
random.shuffle(Ominous_dic)
def Ominous_enc(msg):
res = 0
for idx, word in enumerate(Ominous_dic):
res += random.randint(0, 200) * ord(word) * (2 ** (50 * (idx + 1)))
return res + msg
cipher = Ominous_enc(msg)
print(f'cipher = {cipher}')
本质上还是跟位数相关,res每次加的随机值都是每50位的低位,所以我们可以分段来考虑爆破
每次提取密文的48位(按字节分组才好处理)
具体看代码就能理解了。
from Crypto.Util.number import *
import string
flag_word = (string.ascii_letters + string.digits + '{}@_!').encode()
cipher = 11174132013050242293373893046306047184706656363469879247040688497021
#print(bin(cipher))
flag1="1101010000110101100111101101100"
flag2="011001000100001101011001011000010011001011010111"
flag3="011010000100000001111000010010111000100101010101"
flag4="010111110011000001101101111001101111011010100111"
flag5="011101010111001100100001001000010010000101111101"
Ominous_dic = ['啊', '米', '诺', '斯']
words=[ord(word) for word in Ominous_dic]
#print(words)
"""words=[21834, 31859, 35834, 26031]
for i in words:
for j in range(200):
tmp=int(flag4+flag5,2)
tmp-=i*j*2**50
tmp=long_to_bytes(tmp)
if all(char in flag_word for char in tmp):
print(tmp,i,j)
#b'_0m1nous!!!}' 35834 83"""
"""words=[21834, 31859, 26031]
for i in words:
for j in range(200):
tmp=int(flag3+flag4+flag5,2)
tmp-=i*j*2**100+35834*83*2**50
tmp=long_to_bytes(tmp)
if all(char in flag_word for char in tmp):
print(tmp,i,j)
#b'h@t_i5_0m1nous!!!}' 26031 158"""
"""words=[21834, 31859]
for i in words:
for j in range(200):
tmp=int(flag2+flag3+flag4+flag5,2)
tmp-=i*j*2**150+26031*158*2**100+35834*83*2**50
tmp=long_to_bytes(tmp)
if all(char in flag_word for char in tmp):
print(tmp,i,j)
#b'dCTF{Wh@t_i5_0m1nous!!!}' 31859 42"""
words=[21834]
for i in words:
for j in range(200):
tmp=int(flag1+flag2+flag3+flag4+flag5,2)
tmp-=i*j*2**200+31859*42*2**150+26031*158*2**100+35834*83*2**50
tmp=long_to_bytes(tmp)
if all(char in flag_word for char in tmp):
print(tmp,i,j)
#b'BuildCTF{Wh@t_i5_0m1nous!!!}' 21834 119
ez_matrix
#SageMath 9.5
from Crypto.Util.number import *
from gmpy2 import powmod
from secret import msg
def pad(x, pad_length):
return x + b'\x00' * (pad_length - len(x))
def rsa_gen(bits):
p = getPrime(bits)
q = getPrime(bits)
return p, q
bits = 1024
pad_length = 200
matrix_size = 32
e = 65537
p, q = rsa_gen(bits)
n = p * q
m = bytes_to_long(pad(msg, pad_length))
c = powmod(m, e, n)
p_binary = bin(p).replace('0b', '').zfill(bits)
q_binary = bin(q).replace('0b', '').zfill(bits)
P = matrix(GF(2), [list(map(int, p_binary[i:i+matrix_size])) for i in range(0, len(p_binary), matrix_size)])
Q = matrix(GF(2), [list(map(int, q_binary[i:i+matrix_size])) for i in range(0, len(q_binary), matrix_size)])
gift = P.solve_right(Q)
with open('output', 'w') as file:
file.write(f'c = {c}\n')
file.write(f'p ^ q = {p ^^ q}\n')
file.write('gift:\n')
for row in gift:
file.write(' '.join(map(str, row)) + '\n')
关键点,要能意识到p^q,实际上就是矩阵P+Q,因为都是模2域下的操作,所以都是模2加法。
所以我们就能得到P+Q和Pgift=Q,推导如下:
from Crypto.Util.number import *
from gmpy2 import *
bits = 1024
matrix_size = 32
pxorq = 89144063720545532404936347749976033995959352088369581593483294017916269127126015515514164556238892315116219488234599276283755643115494368387307879815221830970632672104176330851649236203019768799744400071934922875736029236458980333704716550922984411453411523931115952319603510996580835848026227775168231757398
pxorq_binary = bin(pxorq).replace('0b', '').zfill(bits)
gift="0010111001000011001001000100110010100001011111010111010001100001010111110110100100011011011110000111010000100100000001111010110101011110100100110011101001001011111001000101000010000101000000111010111011101111000000101010010010101010110111001010010001111010001011101110010000010001001010111000000111111011000000010110111110001100110110111111000000000111001110100010101110011101011110001100110101010010000010111010110110001100111100010011110010010110100111011100011000110011000001111001001011110011110010110000111001000100100000001011001011111001000101111011110000100000011011010011111001001110000111001001010001000010110101011001000000110011100000001111011001010111101100010000001011111010001101110011111101011001001110000111111111110111110001101100000010010110010010111100000110001111110111111001011001110101001000011100001110000100010110000111111010101011001100101111101100010010000100110110001111111110111001010110000111010000011110011011101101000101100000110110101010100011110000110101111101101101101001000110101100110111"
gift_binary = gift.zfill(bits)
A = matrix(GF(2), [list(map(int, pxorq_binary[i:i+matrix_size])) for i in range(0, len(pxorq_binary), matrix_size)])
B = matrix(GF(2), [list(map(int, gift[i:i+matrix_size])) for i in range(0, len(gift_binary), matrix_size)])
E=identity_matrix(GF(2), 32)
P_1=A.solve_left(B+E)
P=P_1.inverse()
p=""
for i in P:
for j in i:
p+=str(j)
p=int(p,2)
print(p.bit_length(),isPrime(p))
Q=P+A
q=""
for i in Q:
for j in i:
q+=str(j)
q=int(q,2)
print(q.bit_length(),isPrime(q))
n=p*q
phi=(p-1)*(q-1)
e=65537
c = 5750862006780374919287214285692236210204656897730327429454502213453716609006462693326927544526483929921956237739564314742381291228170724611684726314766300684189083862768843433748971907962075938141567163713163231477418107343867114651242407427262164467193346523730926798966915657982552864539513197192523866321569716738540583056085357621328692775578162692288348251605475475005408200801081747601745630186390866011595954211521326069111983199120520535552104591110478015154646709731714695120857959832894595677697407284511806934799265823961155753765208975629786832407640872204810033141414096894416317703257346937008503926274
print(long_to_bytes((int(powmod(c,invert(e,phi),n)))))
#BuildCTF{78e09053-bc0a-4fdc-9dec-0f107bf9ba43}
Ju5t_d3c0de_1t!
e = 'VTJGc2RHVmtYMThUWGplSkN2YzJwazJ2KzJieQ=='
c = 10110011010010110101101101011110100001010100101110111011101101111101101001000010111010010011101111001111111000000001111000000010101
p = 1100010000110101100011011010101011111101001101010011001010110111100011110110101111000101100001011011001100110010010111111100110000001111010111111101111001100111100011100110110011101011111011100111010011000100011001101101111011010110000011011100101010010101110001011011010111001010101101100101011111101000110010111000011010111001101001
q = 11000010010010011110101110100011011100101101100100011011100010111000011110111000000011111100010100100000101101010101000101101101101011011100001101111010001010010011001010110010110101001100100011010110100011110011101110101110111110100000011110101010011011111010111100011000011111001000010101100100011110010000010001110010101100100111001
key = 592924741013363689040199750462798275514934297277010275281372369969899775117892551575873706970423924419480394766364097497072075403342004187895966953143489192628648965081601335846012859223829286606349019
# use m minus key to get the final flag!
解码e,解第一层base64,再解一层的话发现前面为Salt_开头,猜测为Rabbit加密,无密钥解密就得到了
https://tool.oschina.net/encrypt
剩下的都一眼出了(最后根据提示m减一下key就行了)
from Crypto.Util.number import *
from base64 import *
e = 'VTJGc2RHVmtYMThUWGplSkN2YzJwazJ2KzJieQ=='
c = 10110011010010110101101101011110100001010100101110111011101101111101101001000010111010010011101111001111111000000001111000000010101
p = 1100010000110101100011011010101011111101001101010011001010110111100011110110101111000101100001011011001100110010010111111100110000001111010111111101111001100111100011100110110011101011111011100111010011000100011001101101111011010110000011011100101010010101110001011011010111001010101101100101011111101000110010111000011010111001101001
q = 11000010010010011110101110100011011100101101100100011011100010111000011110111000000011111100010100100000101101010101000101101101101011011100001101111010001010010011001010110010110101001100100011010110100011110011101110101110111110100000011110101010011011111010111100011000011111001000010101100100011110010000010001110010101100100111001
key = 592924741013363689040199750462798275514934297277010275281372369969899775117892551575873706970423924419480394766364097497072075403342004187895966953143489192628648965081601335846012859223829286606349019
e=65537
c=int(str(c),2)
p=int(str(p),2)
q=int(str(q),2)
n=p*q
m=pow(c,inverse(e,(p-1)*(q-1)),n)
m=m-key
print(long_to_bytes(m))
#b'I_l1k3_crypt0_5o_h4rd!'
ezzzzz_RSA
import libnum
from Crypto.Util.number import *
flag = b'BuildCTF{*******}'
m = libnum.s2n(flag)
e = 65537
q = getPrime(1024)
q1 = getPrime(1024)
p = getPrime(1024)
p1 = getPrime(1024)
n = p * q
n1 = q * p1
n2 = p * q1
c = pow(m, e, n)
h0 = pow(2023 * p + 2024, q1, n2)
h1 = pow(2024 * p1 + 2023 * q, 113, n1)
h2 = pow(2023 * p1 + 2024 * q, 629, n1)
print(f'n1 = {n1}')
print(f'n2 = {n2}')
print(f'c = {c}')
print(f"h0 = {h0}")
print(f"h1 = {h1}")
print(f"h2 = {h2}")
解出来一个就够m的大小了
解p
from Crypto.Util.number import *
from gmpy2 import *
n2 = 11933661747067216317642315621042074566046499785197709817779978157416906347669444374234313329064859622960743743511735672614999566264025648698589886185056758071718319964262619819143757922916624196354313322456534266520150543008117888101349920396737532937616502689667208207329048979872222563877933742673021891249520999021187404065706388700711208445628041386956459398271230236018476964839399245143666534359113777846535151773174701732284280083586580489995666306373839417946648196140879978268472361473557375951972193618245984950374326806423407152520541682571610372434453778172497925696535270204943842467472100237854318244291
h0 = 2996726009726260695732821166504040344731102637047682432884058857493935625094258046641569918904978173116793673563730117949606727933902262668880339210084101176866383602543966179840353633735507442926707342258391362245904850297416642271123328980812931025677857373199540129280097315832907023777052101133649877194495480543646472133854655383755313968952550827443970931104462445312146328606862802196901953935238972759852435882720786570965542286278549107402918041194008845717507735786897968734831064393337773557817839343449001368565856921138408039931608804233595980497557733714560035682416265029819340316734845279080134432704
p = gcd(pow(2024,n2,n2)-h0,n2)
c = 20080676122944896238797522372441559951736929534371084097400233944319893926800196694449564534150770085554349952433141815637324753386484549616573636001763815852095984830828952020047938406909274311785306299061021662484544371813739713520361343350959698642021322243662988875917088108399877176033404097457939417134483333264562602633853694382014472747500159100723626314928476484037666519857604568300967071868151508142784271042600815406853978696857309760951105852288354603503207383899902135741426285551161292195639862478256231538619968275273876467583013024899054710124331145912185471501398910765579441956531091561893256832468
e=65537
m=long_to_bytes(pow(c,invert(e,p-1),p))
print(m)
#b'BuildCTF{29g5blh5-7829-5k38-a836-9bk54h291h6}'
解q
from Crypto.Util.number import *
from gmpy2 import *
n1 = 19957426023169626195602761840035904096149402534966487535713447987366768645542881124782551268978342063458430846877824210659778126281705984711061190351636497944943321988950188171159903717348936556346198638311950016136865425015037098270040031872702873264144372191898253134939805153141701819590164140250130420280491966786900651186941317959556066730959744279963976065565436153399679475410040773637142677936926894677919242351610457296203864806991539480593546084449323017670431590012312526757477514457145686070196978477495658962519391041011847512041022828710693830661412217389320600888361578917153088073678587422269955710471
h1 = 19843160604742228074331688651361052208481287636527838615063387670722213224954610448720065937378201545177278841575633697012434074186046556843292068835752113384756149944114298949115412819730843598288637259467085268861201775723817790428386595559040938133481222229290199923979132846871398172318539492741755408720073350962388138453341677009547616238262211176727424067946020683742262782319735286357465817786446238528187722959357444676512705451504136333336415880020502524009647940182721264953084120705872870651891290569527156804993340563927419561415555818468261824287933683736509372616293569615247228388443284457740072850735
h2 = 15147052684674827267989051566164167603473413362261253296001082161136918959833294463185335416662127368473980239667918561600741667513285708843081475074688239507330230558331408877583246661862040918410036936505307437329914363201630212163952357444441705663871720438955166472073576526814546767805314463827075388036712200327696168965762177567346966479399896578190111819130000991594490932388132188241726654756368698998232826340969288082645860324404980143489489946490266439447342461483490582149239131554246756547000945718737195930407251232848166108751122870333559461452459416252942341423373918245090162970624108991537972775066
e1=113
e2=629
a=2024
b=2023
tmp1=pow(h1*(pow(b,e1,n1)),e2,n1)
tmp2=pow(h2*(pow(a,e2,n1)),e1,n1)
q=gcd(tmp1-tmp2,n1)
c = 20080676122944896238797522372441559951736929534371084097400233944319893926800196694449564534150770085554349952433141815637324753386484549616573636001763815852095984830828952020047938406909274311785306299061021662484544371813739713520361343350959698642021322243662988875917088108399877176033404097457939417134483333264562602633853694382014472747500159100723626314928476484037666519857604568300967071868151508142784271042600815406853978696857309760951105852288354603503207383899902135741426285551161292195639862478256231538619968275273876467583013024899054710124331145912185471501398910765579441956531091561893256832468
e=65537
m=long_to_bytes(pow(c,invert(e,q-1),q))
print(m)
where is my n?
from Crypto.Util.number import*
from gmpy2 import*
flag = "..."
e=65537
p=getPrime(512)
q=gmpy2.next_prime(p)
n=p*q
phi=(p-1)*(q-1)
d=inverse(e,phi)
c=pow(flag,e,n)
print("c=",c)
print("e=",e)
print("d=",d)
SHCTF第一周的d_known
我自己的博客:SHCTF2024-week1-crypto&其他 - Naby - 博客园 (cnblogs.com)
from Crypto.Util.number import*
from gmpy2 import*
c= 107973408658512316248795675829719026556281556876279221462095299771897472835817102507431099132436173117611783572607408542140665445616624626408781699266046553444252772105867617770124779786841928535661872891635303381758336724610931502145965143374870804147444436791292512235485326451051756451904673491759905663466
e= 65537
d= 62036379179617188220635702722848631787124203142048526951004487465970915306760341332025319712290841316288636152355908585406155087541334717529113872233640624205650204907669681116401961584897042519881342485819364897891612540596760113597723865477121348794797592568686540283535491492936074500143092361821406613969
p_bits=512
q_bits=512
k_phi = e*d -1
pphi = []
for k in range(e,2,-1):
if k_phi % k == 0:
tmp = k_phi // k
if int(tmp).bit_length()==p_bits+q_bits:
pphi.append(tmp)
for k in pphi:
pp=iroot(k,2)[0]
pp=next_prime(pp)
for i in range(100):
flag=long_to_bytes(pow(c,invert(e,pp-1),pp))
if b'BuildCTF' in flag:
print(flag)
exit()
pp=next_prime(pp)
#b'BuildCTF{Y0u_F1nd_7he_n_success7u1_!}'
girls_band_cry_pto
from Crypto.Util.number import *
import gmpy2
def getprime(kbit,FLAG):
a = getPrime(kbit)
b = getPrime(kbit)
N = getPrime(kbit+5)
seed = getPrime(kbit)
t = seed
list_t = []
for i in range(10):
t = (a*t+b)%N
list_t.append(t)
if FLAG:
print(list_t)
return seed
p = getprime(512,1)
q = getprime(512,0)
flag = b'...'
flag = bytes_to_long(flag)
n = p*q
e = 1384626
assert flag.bit_length() < n.bit_length()//2
c = pow(flag,e,n)
print('c=',c)
具体过程我就不讲了,太麻烦了,直接拿一些模板了
第一步利用LCG,求出p
然后发现e和phi(p)不互素,gcd之后为6
直接求e//6的逆,求出m的6次方
发现(p-1)%4=1,利用cipoll算法(参考0xGame一题)进行开平方根
得到m的3次方,最后使用AMM算法开3次根,直接就能秒出了
(直接用AMM跑开6次根貌似出不来)
import math
import random
from Crypto.Util.number import *
from gmpy2 import *
s=[37382128984932009103055100236038298684187701771245912912208816283882352432386956435965036367810667394024993955812239704879381327228911265588017046627348503, 78860822396220922181257740301787328387654351181949135165584053897837116358564567613593406267620270397593757280733139576593428399156673217202739776358215953, 71961258377748802736482119449608198361898650603044501972923193831637292104436919483148544126546157761435847502622416800596454167412705966674707485447149592, 87271087644907910379168026089161507515679859469787715709089631773745967695993043069981508275969979669395420678260957179827954920361899134388830957711827969, 72060448202158281754256475874109091993193239479491265267010728401711694585210195554635415348891139571830347004379216450772696235700910532153698412887476412, 198822737610698203376629161658629276556973499054887457432530950247888991546498594767954251786997515337433684733300663470799887569646159225800449429896258899, 186920895499932700150962847893153648403293237986492275627558112493385728113172211076262656795948951216023567806119078906412693819469136004563793414149643278, 56472634592713718635518027850351194341092172882542912776939953869983486542308422043454035086533070566859787384014556343587278097326244663175874047755695694, 42665120723108982921319232615099077060109901818313520605789700720605479528247045699344736360219784997528870841912999130951916510491705708498185762196467897, 205629005887807114384057131575309344114082007367662384600399313743755704623421415135564859072125246431180953419843187244789534372794288258609006920825136808]
"""
1.Xn+1反推出Xn Xn=(a-1 (Xn+1 - b))%m
2.求a a=((Xn+2-Xn+1)(Xn+1-Xn)-1)%m
3.求b b=(Xn+1 - aXn)%m
4.求m tn=Xn+1-Xn,m=gcd((tn+1tn-1 - tntn) , (tntn-2 - tn-1tn-1))
逆着求
"""
length=len(s)
t = []
for i in range(length-1):
t.append(s[i]-s[i-1])
all_n = []
for i in range(length-3):
all_n.append(gcd((t[i+1]*t[i-1]-t[i]*t[i]), (t[i+2]*t[i]-t[i+1]*t[i+1])))
for n in all_n:
try:
n=abs(n)
if n==1:
continue
a=(s[2]-s[1])*invert((s[1]-s[0]),n)%n
ani=invert(a,n)
b=(s[1]-a*s[0])%n
seed = (ani*(s[0]-b))%n
if isPrime(seed) and seed.bit_length()==512:
p=int(seed)
except:
pass
c= 51846448616255629242918159354807752786692784645460532308823434086479848425723111371477823327980874708898952566998637230358105087254392989515438172155717708590176244736140994735777168368143405720703501031813936741444894000217727880068767785957507824708838189619286341612305393812568642372035793481458142583420
e = 1384626
g=gcd(e,p-1)
e=e//g
m=pow(c,invert(e,(p-1)//g),p)
def square_root_of_quadratic_residue(n, modulo):
"""Square root of quadratic residue
Solve the square root of quadratic residue using Cipolla's algorithm with Legendre symbol
Returns:
int -- if n is a quadratic residue,
return x, such that x^{2} = n (mod modulo)
otherwise, return -1
"""
if modulo == 2:
return 1
if n % modulo == 0:
return 0
Legendre = lambda n: pow(n, modulo - 1 >> 1, modulo)
if Legendre(n) == modulo - 1:
return -1
t = 0
while Legendre(t ** 2 - n) != modulo - 1:
t += 1
w = (t ** 2 - n) % modulo
return (generate_quadratic_field(w, modulo)(t, 1) ** (modulo + 1 >> 1)).x
def generate_quadratic_field(d, modulo=0):
"""Generate quadratic field number class
Returns:
class -- quadratic field number class
"""
assert (isinstance(modulo, int) and modulo >= 0)
class QuadraticFieldNumber:
def __init__(self, x, y):
self.x = x % modulo
self.y = y % modulo
def __mul__(self, another):
x = self.x * another.x + d * self.y * another.y
y = self.x * another.y + self.y * another.x
return self.__class__(x, y)
def __pow__(self, exponent):
result = self.__class__(1, 0)
if exponent:
temporary = self.__class__(self.x, self.y)
while exponent:
if exponent & 1:
result *= temporary
temporary *= temporary
exponent >>= 1
return result
def __str__(self):
return '({}, {} \\sqrt({}))'.format(self.x, self.y, d)
return QuadraticFieldNumber
mp=square_root_of_quadratic_residue(m,p)
mp=[mp,p-mp]
def onemod(e, q):
p = random.randint(1, q-1)
while(powmod(p, (q-1)//e, q) == 1): # (r,s)=1
p = random.randint(1, q)
return p
def AMM_rth(o, r, q): # r|(q-1
assert((q-1) % r == 0)
p = onemod(r, q)
t = 0
s = q-1
while(s % r == 0):
s = s//r
t += 1
k = 1
while((s*k+1) % r != 0):
k += 1
alp = (s*k+1)//r
a = powmod(p, r**(t-1)*s, q)
b = powmod(o, r*a-1, q)
c = powmod(p, s, q)
h = 1
for i in range(1, t-1):
d = powmod(int(b), r**(t-1-i), q)
if d == 1:
j = 0
else:
j = (-math.log(d, a)) % r
b = (b*(c**(r*j))) % q
h = (h*c**j) % q
c = (c*r) % q
result = (powmod(o, alp, q)*h)
return result
def ALL_Solution(m, q, rt, cq, e):
mp = []
for pr in rt:
r = (pr*m) % q
# assert(pow(r, e, q) == cq)
mp.append(r)
return mp
def calc(mp, mq, e, p, q):
i = 1
j = 1
t1 = invert(q, p)
t2 = invert(p, q)
for mp1 in mp:
for mq1 in mq:
j += 1
if j % 100000 == 0:
print(j)
ans = (mp1*t1*q+mq1*t2*p) % (p*q)
if check(ans):
return
return
def ALL_ROOT2(r, q): # use function set() and .add() ensure that the generated elements are not repeated
li = set()
while(len(li) < r):
p = powmod(random.randint(1, q-1), (q-1)//r, q)
li.add(p)
return li
for i in mp:
cp = i % p
mp = AMM_rth(cp, 3, p)
rt1 = ALL_ROOT2(3, p)
amp = ALL_Solution(mp, p, rt1, cp, 3)
for j in amp:
print(long_to_bytes(int(j)))
#b'BuildCTF{crypt0_15_s0_e@5y!}'