BYUCTF2025 crypto WP

1.Many Primes

注意到n是很多小因子的乘积,利用欧拉函数性质计算 解密即可

1
2
3
4
5
6
7
8
9
10
11
12
from Crypto.Util.number import *
n = 84957339878841249042661992015318775914153057891067549723671982778975957526984361748735670333426792012519248099265537115315835602057882318543112781196438953840653279029957533208045448649312183873062132255928109150470090982541502003013666939934181416473581073990221728448342533549843710383544743220364127453679761909368982493089369740815066106196444062558446312836612656666434089655206650558129894180991572670565328419648196602807190683488653617068325238542193033423978598565191919683033996144778397817249870630736098769732268174866389943010980427234356604782502318622853423388492983406635687647680770869588481426436811952986075832678887752706507835771052708232550208582584262345437818916577580806059662945066377375408508814381061305598911972399165132279018674832071994673661875185328115121586302490349253912699566783660070599552395205352917554104371784905394477629626963439266490743240318198729049054547013391348516066097465180775402810975266096525722415778248668765855332776864126033830969325570615444114396786906102536716873598804164196155179833683285635189223166238933318740720918827120989416013091102543382987278707392961157272937695585450287755023671116911370689655292160336521776501052329465384315585357461493649222793172462113102463
flag = 45146787828557679140423580221442956925310977371109091853462843177826294442352634580160310989152235297235514141658881390908592470683795245870619319983451904537192781823855678086088663405872526980084960008183831288044960349605168173490367894375757787452024287989993362954206286853190401541606518731317814018817491109177360761859453002792899864984488524864028766239497641048919565458281765487932324396702580026094746189401141448947513512730220423629277692258527951902039531739842965067285622196418171785466236294324572986853688947727117303227689578683403160426800470263102483582737614730930657875098843867256713854784720793138228809768453579721222271047690131897888999884098995408016105397663714102200568327066068146128637742779637777800612639149916508879936573438036837445673606364763612971401591822166427703422764153960398983100036398400304771376839125152709954274549463602659761299411215766075895177151923436509501196662786766042103493713861194722614436307437016043581292216432028543923347478884441934980948114759937955940408027377458938151172837554432746134399838012547867483350557859826433321810794053681726512471838143910118068486851496148663526948219071671481909824342580081675074372829356225227848676981201731545407466857723499918017
primelist = list(factor(n))
p = [fac[0] for fac in primelist]
phi = n
for i in p
phi *= 1- (1/i)
e = 65537
d = inverse(e,phi)
m = pow(flag,d,n)
print(long_to_bytes(m))

flag:byuctf{3ulers_ph1_function_15_v3ry_us3ful_4nd_th15_I5_a_l0ng_fl4g}

2.PEM

使用openssl打开pub文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
C:\Users\infinite\Downloads>openssl rsa -pubin -in ssh_host_rsa_key.pub -text -noout
Public-Key: (1822 bit)
Modulus:
28:f8:f1:d3:38:48:79:ec:e1:a0:e4:fa:99:0f:de:
e5:9f:83:bc:cf:5f:c4:1d:27:83:a6:57:e3:ca:d4:
f1:81:f0:a1:c2:b7:f6:1e:0f:39:1b:7b:11:af:c5:
02:b0:70:e5:55:a3:9c:14:d9:b3:ea:e6:c8:9e:33:
0e:0f:68:fb:77:89:24:38:e9:3e:6c:1c:c9:48:69:
ce:80:52:5b:59:d0:97:c0:c7:83:16:1a:14:8d:53:
70:fd:4a:de:1e:65:f4:90:60:a7:8b:d7:22:e0:fa:
4e:d6:24:f3:74:7a:4d:61:90:12:2f:d1:b7:78:ca:
5b:bb:d8:5c:a0:4c:ae:13:e1:97:be:52:75:d4:c5:
81:1a:2a:2d:f1:86:e3:74:ad:5f:8b:11:f6:f5:01:
c3:2c:da:a6:ac:11:70:77:96:39:5c:2a:95:7b:5c:
73:98:40:1c:9b:9b:e0:6c:18:dd:b9:79:81:c5:eb:
f1:ec:e7:56:4f:42:b8:44:37:05:06:a0:bc:9d:fc:
2a:e5:46:49:ab:05:ef:48:39:81:e7:d7:ec:d6:d6:
db:ba:ac:dc:4e:80:9c:c5:4a:fa:c4:ce:30:89:43:
c7:c5:e1
Exponent: 65537 (0x10001)

得到公钥,描述中提示 直接使用iroot开根

1
2
3
4
5
6
from gmpy2 import *
from Crypto.Util.number import *
N = 0x28f8f1d3384879ece1a0e4fa990fdee59f83bccf5fc41d2783a657e3cad4f181f0a1c2b7f61e0f391b7b11afc502b070e555a39c14d9b3eae6c89e330e0f68fb77892438e93e6c1cc94869ce80525b59d097c0c783161a148d5370fd4ade1e65f49060a78bd722e0fa4ed624f3747a4d6190122fd1b778ca5bbbd85ca04cae13e197be5275d4c5811a2a2df186e374ad5f8b11f6f501c32cdaa6ac11707796395c2a957b5c7398401c9b9be06c18ddb97981c5ebf1ece7564f42b844370506a0bc9dfc2ae54649ab05ef483981e7d7ecd6d6dbbaacdc4e809cc54afac4ce308943c7c5e1
e = 65537
m = gmpy2.iroot(int(N),2)[0]
print(long_to_bytes(m))

flag:byuctf{P3M_f0rm4t_1s_k1ng}

3.Real-Smooth

chacha20属于流密码,简单来说 此时出现了nonce reuse

1
2
3
cipher = ChaCha20.new(key=key, nonce=nonce)
print(bytes.hex(cipher.encrypt(b'Slide to the left')))
print(bytes.hex(cipher.encrypt(b'Slide to the right')))

由于参数一致,但ChaCha20实例没有重置,是同一个密钥流

前者17位,后者18位

我们需要得到Criss cross, criss cross的密文,一共24位

则24=17+7

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/local/bin/python
from Crypto.Util.number import *
from Crypto.Cipher import ChaCha20
from Crypto.Random import get_random_bytes
from pwn import *
msg1 = b'Slide to the left'
msg2 = b'Slide to the right'
ct1 = bytes.fromhex("5fcba2305c953edf4f17c548f6d557d0ef") #from interactive
ct2 = bytes.fromhex("919d44734ab669aaaa338153c725c1b34d8e")
keystream1 = xor(ct1, msg1)
keystream2 = xor(ct2, msg2)[:7]
ct3 = xor(b'Criss cross, criss cross',keystream1+keystream2)
print(bytes.hex(ct3))
#submit to get flag

flag:byuctf{ch4ch4_sl1d3?...n0,ch4ch4_b1tfl1p}

4.Anaken21sec1

加密流程:

transform to matrix->do the block permutations and additions->scramble matrix->get resulting letters from matrix-> rearrange ciphertext according to the key

when we are recovering,we should be in the reversed order

inverse add,permute

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def inverse_permute(matrix, count):
inv_matrix = np.zeros_like(matrix)
perm_matrix = permutes[count]
for i in range(6):
for j in range(6):
original_pos = int(perm_matrix[i,j] - 1)
orig_i, orig_j = divmod(original_pos, 6)
inv_matrix[orig_i, orig_j] = matrix[i,j]
return inv_matrix
def inverse_add(matrix, count):
temp = matrix.copy()
if count == 0:
temp[(np.arange(6)[:,None] + np.arange(6)) % 2 == 0] -= 1
elif count == 1:
temp[3:,3:] = (temp[3:,3:] - temp[:3,:3]) % 3
elif count == 2:
temp[:3,:3] = (temp[:3,:3] - temp[3:,3:]) % 3
elif count == 3:
temp[3:,:3] = (temp[3:,:3] - temp[:3,3:]) % 3
elif count == 4:
temp[:3,3:] = (temp[:3,3:] - temp[3:,:3]) % 3
return temp % 3

decrypt function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
def decrypt(ciphertext, key):
# key list
keyNums = [ord(k) - 97 for k in key]
uniqueKeyNums = []
[uniqueKeyNums.append(x) for x in keyNums if x not in uniqueKeyNums]

# reverse box
num_boxes = len(uniqueKeyNums)
base_size = len(ciphertext) // num_boxes
remainder = len(ciphertext) % num_boxes
box_sizes = [base_size + (1 if i < remainder else 0) for i in range(num_boxes)]

# index
sorted_box_indices = sorted(range(num_boxes), key=lambda x: uniqueKeyNums[x])

# sort
boxes = [''] * num_boxes
current_pos = 0
for box_idx in sorted_box_indices:
size = box_sizes[box_idx]
boxes[box_idx] = ciphertext[current_pos:current_pos+size]
current_pos += size
# recover text
max_len = max(len(box) for box in boxes)
reconstructed = []
for i in range(max_len):
for box in boxes:
if i < len(box):
reconstructed.append(box[i])
reconstructed_text = ''.join(reconstructed)
block_size = 12
num_blocks = len(reconstructed_text) // block_size
plaintext = []

# reverse to matrix
for block_idx in range(num_blocks):
block = reconstructed_text[block_idx*block_size:(block_idx+1)*block_size]
matrix = np.zeros((6, 6))
for row in range(6):
if row < len(block)//2:
char = block[row]
num = 0 if char == '0' else ord(char) - 96
matrix[row, 0] = num // 9
matrix[row, 1] = (num % 9) // 3
matrix[row, 2] = num % 3
print(num)
if row + 6 < len(block):
char = block[row + 6]
num = 0 if char == '0' else ord(char) - 96
matrix[row, 3] = num // 9
matrix[row, 4] = (num % 9) // 3
matrix[row, 5] = num % 3
# reverse add,permute
for keyNum in reversed(keyNums):
matrix = inverse_add(matrix, keyNum % 5)
matrix = inverse_permute(matrix, (keyNum // 5) % 5)
print(matrix)
# matrix to characters
plaintext_block = [''] * 12
for row in range(6):
num = int(9*matrix[0,row] + 3*matrix[1,row] + matrix[2,row])
plaintext_block[row] = chr(num + 96) if num != 0 else '0'
num = int(9*matrix[3,row] + 3*matrix[4,row] + matrix[5,row])
plaintext_block[row+6] = chr(num + 96) if num != 0 else '0'

plaintext.extend(plaintext_block)

return ''.join(plaintext).rstrip('x')
print(decrypt("cnpiaytjyzggnnnktjzcvuzjexxkvnrlfzectovhfswyphjt","orygwktcjpb"))

flag:byuctf{revisreallythestartingpointformostcategoriesiydk}

5.Choose Your RSA

拥有输入三个e的机会

可以尝试构建同余方程组,不妨令e=2,3,6 注意到 using Chinese_remain_theorm

because m << n0n1n2

so we get key^6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from Crypto.Cipher import AES
from Crypto.Util.number import bytes_to_long, getPrime
from Crypto.Util.Padding import *
import binascii
import os
ct = binascii.unhexlify("3ccdef4558c4b9b365c1b346d23b172ed5cdc1b9508e6512ca2d19b799629cbc883c3b2cb0ed650a082176d0e90d36d0ae639131836feac2781f93b52cb76799")
n0=12901047897865564085005555494848516786943017492507319459684131435116543351051613057026894715077022349305179949121422952599616744041493024554562993621375461610570934176855847094053213337460105832748672080229639152970185240782125614620198241734290994145195499301621714236213293548256539300545926430478951983631896561675018313002435534462457819446089057174455445182488698651830504909555136837148264038569576255015280355911562880162351708222586626152149260752722632950832067823701290958895391835409385346453980132313333156113548712591773630157779433143550718642814374972809331140477401356430798130365758853338241256769229
c0=10502892313090682763822680962011469009121098931562931096039602236208816458303855453549930257560665687129350428369433036883112390675535343584754410295663318436790755007194168120952930789593039968684231000346571478300886085517481597169815339083442607084247136845616617099268066314243219977915214252426041029344006770387033890939856399379369704904418529239278574360064636665812163161693960278007936376476278941341932385358527630110605377555670689273024647081985753002902794207932686832500868459267793206084720203664339763636655642881281956854804740449062554566583294755270879426964176946911512880377456197623944539211347
n1=3295061896934810112199479158124129582967171782692552767409337044815328792352394071852380451112092088155255110812165488667388687973391760179483079619953978890422225870165746099103705999000516614227602629223576807675042403670706115418208468151613923513220590228897359375432680842780892927559224039568350730830116356425994321259660516361592619814700251799208483704870333945172030865914081507353700942387719192509717936754413234481940481849351472631337326249838310033027233010778802215790099695362373599656390754615016770897273644177532219701196857815502028742702858086282312735045997127030926101990456679425417532746150287931572817214559451565323558258340327691288724771724790585382077716144330774265328395472924785136235789896771394829584798059554469208996689722071833879556988826928181224531341969586754302621026082798093845604886522629323113635145651402551938297302931192314196108254689220214299053172800918737096150224637131
c1=2260897399063002146387641839624716510391500672185646250934652825943120723442354137744194967860267409203731960928880471346726230407013260935617265668199531173493405347279965669178670173867570544310608409715824087948261418254698855900271786600169450490511670545527620332136389510799035789439333101326885441811193077441586658636610113514058505670248108962019670027295241575518156075687291568242063813128890924026724171111124817807007697321972633490454945140039265150404766565411789527529080352318124752058048301522383438572552448044455695333190920161040592419415703177267134205287860325681589567775986343054729114319325761313737830216905588698678047156230343084313466992425361172103511684143215700688618239000544475507256224539725337986870687949251002168710303401595118898299210904639383663504200568547016253661152702856809564275802702333968537033173767125208790706642301921409054346004435214406838824925441785110092968619703427
n2=534856649999293006646965707236844367879579644306582178987047886996679623225009977037982163446712883350881830528405301425333143620836525920508725329226747074104846894446455952892514557313176553423777697153180761277147862371488939470932737218954209404299849357184984097083651774889042638462226878103438887930566846514925831464659544903313713649832966359667299089031676414520995877125825805929034266666185819750396385130705153027961707682760581148960192927429700829608609669533290032472050130053203873533808358514924592371709810466003560178689198725595563761615921657464739966895860692469642032094853840769829208970622747072652688811814301793923896818231351018864043431257743452439579413981004936638002281268734476869662509393257634019795504342878138624311280707838784574671674441194900219118837664517551134658009058563526195974672554105704491186712894744713312067360412998148974453476620815022523197976629296068742797068875138669419501112789419552725365803409199304932612296164410185805699387763520547507703122003082986594532566634940505345301060731129181533994403221953168141020670469942592859374996230982091517959880556509176573190971386036296195900417423198495317855476647754548950599374914294895602028491258863344612471906172684901
c2=419977647936474802808007520512202392751196186012143173258860219824058438574060054243234195719764363776066899349262850026899497713411098409435098959736744226582526488947516752759208661945632728592946380099912384069012373545191761201337219718672267458474128776931393793768078208896908961213663631156984975882294629801343288699988356348579176718733398987339378639761465153558262375922153594463383295140492711761698371492793097376542422353586207861569761209748085341984544197078477549825985604229077037151255246577926990201484334752492127910130653690091377815356410353233255693869176242511057184789819924011450763884703947165734785698297964959405472013852838118613424816148066297901811777287302947611911773412378511526549181770043970232304212579187301670855221735879988994258480092718835531369579910201440589715816512706638295345822213208863594674237856732739530992728906484095552793718089988859890830501766470953925979084677596869766274164941761659118360051925109528163275675868450163542095445255634165507672936048276699938984285391960617791052639734034082166655638753191519213494387022986841946774585620175472935323135105825961916816389024933650104029158294814151410947077366776442912660785563736329254577395925171323970442207337567371
C0 = c0^3
C1 = c1^2
x = crt([C0,C1,c2],[n0,n1,n2])
key = long_to_bytes(gmpy2.iroot(x,6)[0])
cipher = AES.new(key[:16], AES.MODE_ECB)
flag = cipher.decrypt(ct)
print(unpad(flag,AES.block_size))

flag:byuctf{Chin3s3_rema1nd3r_th30r3m_is_Sup3r_H3lpful}