iT邦幫忙

2023 iThome 鐵人賽

DAY 14
0
Security

資安小白的密碼學從0到1-CryptoHack平台解題紀錄系列 第 14

【Day 14-1】Modular Arithmetic 06 - Adrien's Signs

  • 分享至 

  • xImage
  •  

前言

今天會分兩篇發,一篇一題這樣,因為發現兩題合再一起好像文章會太長,解的題目如下
https://ithelp.ithome.com.tw/upload/images/20230924/20162613i2uMU94L2f.png

Writeup

Adrien's Signs

題目

網址 : https://cryptohack.org/courses/modular/adrien/
https://ithelp.ithome.com.tw/upload/images/20230924/201626133x4HpAGRbw.png

思路

先把題目給的source跟output下載下來
從source code 先看他是怎麼加密的

  • source code
a = 288260533169915
p = 1007621497415251

FLAG = b'crypto{????????????????????}'


def encrypt_flag(flag):
    ciphertext = []
    plaintext = ''.join([bin(i)[2:].zfill(8) for i in flag])
    for b in plaintext:
        e = randint(1, p)
        n = pow(a, e, p)
        if b == '1':
            ciphertext.append(n)
        else:
            n = -n % p
            ciphertext.append(n)
    return ciphertext
print(encrypt_flag(FLAG))

看出,他會把flag的每個字元利用bin把它變成2進位後,加到"plaintext"這個字串

代表plaintext字串中只會出現"0"跟"1"
[bin(i)[2:].zfill(8) for i in flag]
[2:]目的是為了忽略前面的0b
zfill(8)為,如果該字元轉成二進位未滿8位數,那麼在前面補0,比如說某字元轉二進為"10011",便會把它補成"00010011"

之後用迴圈去跑plaintext這個字串,e會是一個在1~p之間的隨機整數
n = pow(a, e, p)用數學式表示,則為𝑛≡𝑎^𝑒 (𝑚𝑜𝑑 𝑝)
下面判斷
如果b為1,就把n直接加到ciphertext後面
否則把-n % p 加到ciphertext後面

最後回傳ciphertext
而ciphertext也就是題目給的output

解法

目標 : 得出當時的plaintext字串,把此二進位字串轉換成字元輸出,得到flag

題目給了𝑎跟𝑝,所以我們可以先利用𝐿𝑒𝑔𝑒𝑛𝑑𝑟𝑒 𝑠𝑦𝑚𝑏𝑜𝑙看𝑎是否為模𝑝的二次剩餘

  • code
a = 288260533169915
p = 1007621497415251
print(pow(a, (p-1)//2, p))
  • output
    https://ithelp.ithome.com.tw/upload/images/20230924/20162613KcTVAsd4uA.png

因為 output為1,所以𝑎為模𝑝的二次剩餘
此時就可以利用之前學到的二次剩餘性質
https://ithelp.ithome.com.tw/upload/images/20230924/20162613jPOHIsteeG.png
得知二次剩餘 * 二次剩餘 = 二次剩餘
可得小結論

  • 𝑎的冪次方模𝑝也是二次剩餘

𝑎^𝑒 可看成 𝑎 * 𝑒次𝑎 - > 二次剩餘 * 二次剩餘

好,有此結論後,我們來再看一下source code

n = pow(a, e, p)
if b == '1':
    ciphertext.append(n)
else:
    n = -n % p
    ciphertext.append(n)

可以知道,如果b = 1的話,會直接把n加到ciphertext後面
而n為𝑎^𝑒 (𝑚𝑜𝑑 𝑝),結合剛剛的小結論

  • 如果n為二次剩餘,那麼b = 1,也就是當時plaintext跑到的數字為1,
    反之如果n不是二次剩餘,那麼b = 0,也就是當時plaintext跑到的數字為0

所以我們先設一個空字串(在此名為 flag ),之後利用迴圈,跑當時的output
且判斷pow(n,(p-1)//2, p)是否為1
是的話就把"1"加到flag後面
否則把"0"加到flag後面
最後即可得到當時的plaintext!

  • code
for n in output :
    judge = pow(n,(p-1)//2, p)
    if judge == 1 :
        flag += "1"
    else :
        flag += "0"

我們得到了一個都是0跟1的字串,之後可以以每8個為一單位切割字串,並轉成字元輸出,即可獲得flag !

  • 完整code
output = [67594220461269, 501237540280788, 718316769824518, 296304224247167, 48290626940198, 30829701196032, 521453693392074, 840985324383794, 770420008897119, 745131486581197, 729163531979577, 334563813238599, 289746215495432, 538664937794468, 894085795317163, 983410189487558, 863330928724430, 996272871140947, 352175210511707, 306237700811584, 631393408838583, 589243747914057, 538776819034934, 365364592128161, 454970171810424, 986711310037393, 657756453404881, 388329936724352, 90991447679370, 714742162831112, 62293519842555, 653941126489711, 448552658212336, 970169071154259, 339472870407614, 406225588145372, 205721593331090, 926225022409823, 904451547059845, 789074084078342, 886420071481685, 796827329208633, 433047156347276, 21271315846750, 719248860593631, 534059295222748, 879864647580512, 918055794962142, 635545050939893, 319549343320339, 93008646178282, 926080110625306, 385476640825005, 483740420173050, 866208659796189, 883359067574584, 913405110264883, 898864873510337, 208598541987988, 23412800024088, 911541450703474, 57446699305445, 513296484586451, 180356843554043, 756391301483653, 823695939808936, 452898981558365, 383286682802447, 381394258915860, 385482809649632, 357950424436020, 212891024562585, 906036654538589, 706766032862393, 500658491083279, 134746243085697, 240386541491998, 850341345692155, 826490944132718, 329513332018620, 41046816597282, 396581286424992, 488863267297267, 92023040998362, 529684488438507, 925328511390026, 524897846090435, 413156582909097, 840524616502482, 325719016994120, 402494835113608, 145033960690364, 43932113323388, 683561775499473, 434510534220939, 92584300328516, 763767269974656, 289837041593468, 11468527450938, 628247946152943, 8844724571683, 813851806959975, 72001988637120, 875394575395153, 70667866716476, 75304931994100, 226809172374264, 767059176444181, 45462007920789, 472607315695803, 325973946551448, 64200767729194, 534886246409921, 950408390792175, 492288777130394, 226746605380806, 944479111810431, 776057001143579, 658971626589122, 231918349590349, 699710172246548, 122457405264610, 643115611310737, 999072890586878, 203230862786955, 348112034218733, 240143417330886, 927148962961842, 661569511006072, 190334725550806, 763365444730995, 516228913786395, 846501182194443, 741210200995504, 511935604454925, 687689993302203, 631038090127480, 961606522916414, 138550017953034, 932105540686829, 215285284639233, 772628158955819, 496858298527292, 730971468815108, 896733219370353, 967083685727881, 607660822695530, 650953466617730, 133773994258132, 623283311953090, 436380836970128, 237114930094468, 115451711811481, 674593269112948, 140400921371770, 659335660634071, 536749311958781, 854645598266824, 303305169095255, 91430489108219, 573739385205188, 400604977158702, 728593782212529, 807432219147040, 893541884126828, 183964371201281, 422680633277230, 218817645778789, 313025293025224, 657253930848472, 747562211812373, 83456701182914, 470417289614736, 641146659305859, 468130225316006, 46960547227850, 875638267674897, 662661765336441, 186533085001285, 743250648436106, 451414956181714, 527954145201673, 922589993405001, 242119479617901, 865476357142231, 988987578447349, 430198555146088, 477890180119931, 844464003254807, 503374203275928, 775374254241792, 346653210679737, 789242808338116, 48503976498612, 604300186163323, 475930096252359, 860836853339514, 994513691290102, 591343659366796, 944852018048514, 82396968629164, 152776642436549, 916070996204621, 305574094667054, 981194179562189, 126174175810273, 55636640522694, 44670495393401, 74724541586529, 988608465654705, 870533906709633, 374564052429787, 486493568142979, 469485372072295, 221153171135022, 289713227465073, 952450431038075, 107298466441025, 938262809228861, 253919870663003, 835790485199226, 655456538877798, 595464842927075, 191621819564547]

a = 288260533169915
p = 1007621497415251
flag = ""

for n in output :
    judge = pow(n,(p-1)//2, p)
    if judge == 1 :
        flag += "1"
    else :
        flag += "0"

for i in range(0, len(flag), 8):
    flag_split = flag[i : i + 8]
    print(chr(int(flag_split, 2)), end='')
  • output
    https://ithelp.ithome.com.tw/upload/images/20230924/20162613NoVLmcddoC.png

flag : crypto{p4tterns_1n_re5idu3s}

統整

這題主要利用𝐿𝑒𝑔𝑒𝑛𝑑𝑟𝑒 𝑠𝑦𝑚𝑏𝑜𝑙快速判斷是否為二次剩餘
之後利用二次剩餘性質解題!
https://ithelp.ithome.com.tw/upload/images/20230924/201626134HiPl11dJU.png


上一篇
【Day 13】模運算相關定理統整筆記
下一篇
【Day 14-2】Modular Arithmetic 07 - Modular Binomials
系列文
資安小白的密碼學從0到1-CryptoHack平台解題紀錄31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言