cryptohack을 공부하면서 얻은 지식들을 정리하려고 한다.
Greatest Common DIvisor
GCD 즉 최대공약수에 대한 내용이다. 유클리드 호제법을 이용해서 두 정수의 최대공약수를 구하라고 한다. 이전에 유클리드 호제법을 다루었던 적이 있다.
2024.07.18 - [BOJ/이론] - 유클리드 호제법과 최대공약수, 최소공배수 python으로 구현하기
유클리드 호제법과 최대공약수, 최소공배수 python으로 구현하기
유클리드 호제법이란?호제법이란 말은 두 수가 서로 상대방 수를 나누어서 결국 원하는 수를 얻는 알고리즘을 나타낸다.호제법(互除法)이라는 단어가 따로 있는것은 아니고, 서로(互) 나누기(除
nivr4y.tistory.com
def gcd(a, b):
while b > 0:
a, b = b, a % b
return a
print(gcd(66528,52920))
1512
Extended GCD
확장된 유클리드 알고리즘은 두 양의 정수 $a$,$b$가 있을때 베주 항등식이라 불리는 아래의 식에서 $u$,$v$의 값을 찾아내는 효율적인 방법이다.
$$ \displaystyle{\displaylines{a·u + b ·v = gcd(a,b)}} $$
자세한 내용은 이전에 다루었던 글을 참고하자.
2024.09.23 - [BOJ/이론] - Extended Euclidean Algorithm (확장된 유클리드 호제법)
Extended Euclidean Algorithm (확장된 유클리드 호제법)
확장된 유클리드 호제법이란?2024.07.18 - [BOJ/이론] - 유클리드 호제법과 최대공약수, 최소공배수 python으로 구현하기 유클리드 호제법과 최대공약수, 최소공배수 python으로 구현하기유클리드 호
nivr4y.tistory.com
def eea(a, b):
x,y, u,v = 0,1, 1,0
while b != 0:
q, r = a//b, a%b
m, n = x-u*q, y-v*q
a,b, x,y, u,v = b,r, u,v, m,n
gcd = a
return gcd, x, y
print(eea(32321,26513))
-8404
Modular Arithmetic 1
모듈러 연산에 대해 설명해준다. $m$이 $a$로 나누어 떨어질때, $a|m$라고 표기하거나 $a\equiv 0\; mod\; m$이라고 표기할 수 있다. 아래의 식에서 $x,y$ 중에 더 작은 값을 넣어주면 된다.
$$ 11\equiv x\; mod\; 6 $$
$$ 8146798528947\equiv y\; mod\; 17$$
4
Modular Arithmetic 2
이번엔 여러 용어들에 대해 설명해준다. $p$가 소수일때, 유한체 $\mathbb{F}_p$를 정의할 수 있는데, 이 유한체 $\mathbb{F}_p$는 $\{0, 1, 2, \ldots, p-1\} $의 원소들로 구성되어 있다. 또한 유한체의 모든 원소 $a$는 $a + b_+ = 0 \; ,\; a \cdot b_* = 1 $ 인 덧셈의 역원$(b_+)$과 곱셈의 역원$(b_*)$을 가진다.
$ 3^{17}\mod 17 $과 $ 5^{17}\mod 17$을 계산해보라고 한다. 이를 계산할때 페르마의 소정리를 이용할 수 있다.
페르마의 소정리는 아래과 같다.
$$ p\text{가 소수이면, 모든 정수 }a\text{에 대해 } a^p\equiv a\left({\rm mod}\ p\right) \text{이다.}$$
이는 동치인 아래의 정리로 바꿀 수 있다.
$$ p\text{가 소수이면, 모든 정수 }a\text{에 대해 } a^{p-1}\equiv 1\left({\rm mod}\ p\right) \text{이다.}$$
위 정리들을 이용해 문제에서 요구하는 $ 273246787654^{65536} \mod 65537 $을 계산해보자. 위의 두번째 정리와 같은 형태이고, 문제에서 $p$는 소수라고 주어졌기 때문에 계산이 필요 없이 답이 1인것을 구할 수 있다.
1
Modular Inverting
유한체 $\mathbb{F}_p$의 원소 중 하나인 $g$에 대해, $g \cdot d \equiv 1 \mod p$ 를 만족하는 유한체 내의 유일한 정수 $d$가 존재한다고 한다.
$ d=3^{-1}$의 역원, 즉 $3 \cdot d \equiv 1 \mod 13$을 만족하는 정수를 찾아보자.
위의 페르마의 소정리를 다음과 같이 변형할 수 있다. $ a \cdot a^{p-2}\equiv 1\left({\rm mod}\ p\right) $이므로, $ 3 \cdot 3^{13-2}\equiv 1\left({\rm mod}\ 13\right) $이라고 할 수 있다.
pow(3, 13-2, 13)
아래와 같이 간단하게 구할 수도 있다.
from Crypto.Util.number import inverse
inverse(3, 13)
9
Quadratic Residues
이번에는 모듈러 연산에서 제곱근에 대해 설명해준다. $p=29, a=11$일때, $a^2=5\mod 29$이므로 우리는 11을 5의 제곱근이라고 부를 수 있다. 이번에는 $a^2=18$일때를 알아보자. a=1부터 a=p-1까지 모두 생각해봐도, $a^2=18$의 제곱근을 찾을 수 없다. 즉, $F_p^{*} $의 모든 원소들이 제곱근을 가지는 것은 아니라는 것을 알 수 있다. 대략적으로, 유한체의 원소들 중 절반 정도가 제곱근을 가지지 않는다고 한다.
$a^2=x\mod p$인 $a$가 존재할 때, 우리는 $x$를 2차 잉여(Quadratic Residue)라고 한다. 반대로, $a^2=x\mod p$인 $a$가 존재하지 않을때, 그 정수를 2차 비잉여(Quadratic Non-Residue)라고 한다.
p=29, ints=[14,6,11]일때, ints 리스트 중에서 quadratic residue를 구하고 그것의 제곱근을 구하라고 한다. 제곱근이 여러개가 가능한 경우에는, 더 작은 것을 출력해야 한다.
p = 29
ints = [14, 6, 11]
qr = [a for a in range(p) if pow(a,2,p) in ints]
print(f"flag {min(qr)}")
8
Legendre Symbol
위처럼 p=29같이 숫자가 작을때는 하나하나 찾아봐도 괜찮지만, 숫자가 커지면 제곱근을 찾는데 시간이 굉장히 오래 걸릴 것이다. 다행히도, 단순한 계산으로 정수가 quadratic residue인지 확인할 수 있는 방법인 르장드르 기호(Legendre Symbol)가 있다.
르장드르 기호에 대해 알아보기 전에, quadratic residue에 관한 특이한 성질을 알아보자.
Quadratic Residue * Quadratic Residue = Quadratic Residue
Quadratic Residue * Quadratic Non-residue = Quadratic Non-residue
Quadratic Non-residue * Quadratic Non-residue = Quadratic Residue
quadratic residue가 마치 +1과 -1의 연산처럼 작동한다!!
르장드르 기호는$\left( \frac{a}{p} \right) \equiv a^{\frac{p-1}{2}} \mod p$와 같이 나타내고, 다음과 같은 성질을 따른다.
- a가 quadratic residue이고 $a \not\equiv 0 \mod p$이면 $\left( \frac{a}{p} \right) = 1$이다.
- a가 quadratic non-residue이고 $a \not\equiv 0 \mod p$이면 $\left( \frac{a}{p} \right) = -1$이다.
- $a \equiv 0 \mod p$이면 $\left( \frac{a}{p} \right) = 0$이다
이말은, $ a^{\frac{p-1}{2}} \mod p$를 계산하면 a가 quadratic residue인지 바로 판단할 수 있다는 것이다.
문제의 output.txt에서는 1024비트짜리 소수와 10개의 정수를 준다. 여기서 quadratic residue를 찾고 그것의 제곱근을 찾으면 된다.
p = 101524035174539890485408575671085261788758965189060164484385690801466167356667036677932998889725476582421738788500738738503134356158197247473850273565349249573867251280253564698939768700489401960767007716413932851838937641880157263936985954881657889497583485535527613578457628399173971810541670838543309159139
ints = [25081841204695904475894082974192007718642931811040324543182130088804239047149283334700530600468528298920930150221871666297194395061462592781551275161695411167049544771049769000895119729307495913024360169904315078028798025169985966732789207320203861858234048872508633514498384390497048416012928086480326832803, 45471765180330439060504647480621449634904192839383897212809808339619841633826534856109999027962620381874878086991125854247108359699799913776917227058286090426484548349388138935504299609200377899052716663351188664096302672712078508601311725863678223874157861163196340391008634419348573975841578359355931590555, 17364140182001694956465593533200623738590196990236340894554145562517924989208719245429557645254953527658049246737589538280332010533027062477684237933221198639948938784244510469138826808187365678322547992099715229218615475923754896960363138890331502811292427146595752813297603265829581292183917027983351121325, 14388109104985808487337749876058284426747816961971581447380608277949200244660381570568531129775053684256071819837294436069133592772543582735985855506250660938574234958754211349215293281645205354069970790155237033436065434572020652955666855773232074749487007626050323967496732359278657193580493324467258802863, 4379499308310772821004090447650785095356643590411706358119239166662089428685562719233435615196994728767593223519226235062647670077854687031681041462632566890129595506430188602238753450337691441293042716909901692570971955078924699306873191983953501093343423248482960643055943413031768521782634679536276233318, 85256449776780591202928235662805033201684571648990042997557084658000067050672130152734911919581661523957075992761662315262685030115255938352540032297113615687815976039390537716707854569980516690246592112936796917504034711418465442893323439490171095447109457355598873230115172636184525449905022174536414781771, 50576597458517451578431293746926099486388286246142012476814190030935689430726042810458344828563913001012415702876199708216875020997112089693759638454900092580746638631062117961876611545851157613835724635005253792316142379239047654392970415343694657580353333217547079551304961116837545648785312490665576832987, 96868738830341112368094632337476840272563704408573054404213766500407517251810212494515862176356916912627172280446141202661640191237336568731069327906100896178776245311689857997012187599140875912026589672629935267844696976980890380730867520071059572350667913710344648377601017758188404474812654737363275994871, 4881261656846638800623549662943393234361061827128610120046315649707078244180313661063004390750821317096754282796876479695558644108492317407662131441224257537276274962372021273583478509416358764706098471849536036184924640593888902859441388472856822541452041181244337124767666161645827145408781917658423571721, 18237936726367556664171427575475596460727369368246286138804284742124256700367133250078608537129877968287885457417957868580553371999414227484737603688992620953200143688061024092623556471053006464123205133894607923801371986027458274343737860395496260538663183193877539815179246700525865152165600985105257601565]
quadratic resiude를 찾으면 $ a^{\frac{p-1}{2}} \equiv 1\mod p$일테니, 다음과 같이 변형해준다.
$$ \left( \frac{a}{p} \right) = 1 \\
\left( \frac{a}{p} \right) \cdot a = a \\
a^{\frac{p - 1}{2}} \cdot a = a \\
a^{\frac{p + 1}{2}} \equiv a \mod p \\
\sqrt{a} \equiv a^{\frac{p + 1}{4}} \mod p $$
$ a^{\frac{p+1}{4}} \mod p$를 계산하면 a의 제곱근을 찾을 수 있다는 말이다!! 주의할 것은 $p\equiv 3 \mod 4$ 형태의 소수에만 가능하다는 것이다.
p = 101524035174539890485408575671085261788758965189060164484385690801466167356667036677932998889725476582421738788500738738503134356158197247473850273565349249573867251280253564698939768700489401960767007716413932851838937641880157263936985954881657889497583485535527613578457628399173971810541670838543309159139
ints = [25081841204695904475894082974192007718642931811040324543182130088804239047149283334700530600468528298920930150221871666297194395061462592781551275161695411167049544771049769000895119729307495913024360169904315078028798025169985966732789207320203861858234048872508633514498384390497048416012928086480326832803, 45471765180330439060504647480621449634904192839383897212809808339619841633826534856109999027962620381874878086991125854247108359699799913776917227058286090426484548349388138935504299609200377899052716663351188664096302672712078508601311725863678223874157861163196340391008634419348573975841578359355931590555, 17364140182001694956465593533200623738590196990236340894554145562517924989208719245429557645254953527658049246737589538280332010533027062477684237933221198639948938784244510469138826808187365678322547992099715229218615475923754896960363138890331502811292427146595752813297603265829581292183917027983351121325, 14388109104985808487337749876058284426747816961971581447380608277949200244660381570568531129775053684256071819837294436069133592772543582735985855506250660938574234958754211349215293281645205354069970790155237033436065434572020652955666855773232074749487007626050323967496732359278657193580493324467258802863, 4379499308310772821004090447650785095356643590411706358119239166662089428685562719233435615196994728767593223519226235062647670077854687031681041462632566890129595506430188602238753450337691441293042716909901692570971955078924699306873191983953501093343423248482960643055943413031768521782634679536276233318, 85256449776780591202928235662805033201684571648990042997557084658000067050672130152734911919581661523957075992761662315262685030115255938352540032297113615687815976039390537716707854569980516690246592112936796917504034711418465442893323439490171095447109457355598873230115172636184525449905022174536414781771, 50576597458517451578431293746926099486388286246142012476814190030935689430726042810458344828563913001012415702876199708216875020997112089693759638454900092580746638631062117961876611545851157613835724635005253792316142379239047654392970415343694657580353333217547079551304961116837545648785312490665576832987, 96868738830341112368094632337476840272563704408573054404213766500407517251810212494515862176356916912627172280446141202661640191237336568731069327906100896178776245311689857997012187599140875912026589672629935267844696976980890380730867520071059572350667913710344648377601017758188404474812654737363275994871, 4881261656846638800623549662943393234361061827128610120046315649707078244180313661063004390750821317096754282796876479695558644108492317407662131441224257537276274962372021273583478509416358764706098471849536036184924640593888902859441388472856822541452041181244337124767666161645827145408781917658423571721, 18237936726367556664171427575475596460727369368246286138804284742124256700367133250078608537129877968287885457417957868580553371999414227484737603688992620953200143688061024092623556471053006464123205133894607923801371986027458274343737860395496260538663183193877539815179246700525865152165600985105257601565]
roots = list()
for a in ints:
if pow(a,(p-1)//2,p)==1:
roots.append(pow(a,(p+1)//4,p))
print(max(roots))
93291799125366706806545638475797430512104976066103610269938025709952247020061090804870186195285998727680200979853848718589126765742550855954805290253592144209552123062161458584575060939481368210688629862036958857604707468372384278049741369153506182660264876115428251983455344219194133033177700490981696141526
Modular Square Root
이산 제곱근을 구하는 구하는 효율적인 또다른 방법은 Tonelli-shanks라고 불린다.
2를 제외한 모든 소수들은 $p\equiv 1 \mod 4$나 $p\equiv 3 \mod 4$의 형태로 나타난다. $p\equiv 3 \mod 4$ 형태의 소수는 이전 문제에서 봤듯이 페르마의 소정리로 간단하게 구할 수 있다. 하지만 $p\equiv 1 \mod 4$ 형태의 소수들은 구할 수 없기 때문에, 보다 일반적인 방법이 필요하다.
Tonelli-shanks는, $r^2 \equiv a \mod p$의 형태에서 r을 구할 수 있다. 주의할 것은, Tonelli-shanks는 합성수 모듈러에서는 작동하지 않는다는 것이다.
a = 8479994658316772151941616510097127087554541274812435112009425778595495359700244470400642403747058566807127814165396640215844192327900454116257979487432016769329970767046735091249898678088061634796559556704959846424131820416048436501387617211770124292793308079214153179977624440438616958575058361193975686620046439877308339989295604537867493683872778843921771307305602776398786978353866231661453376056771972069776398999013769588936194859344941268223184197231368887060609212875507518936172060702209557124430477137421847130682601666968691651447236917018634902407704797328509461854842432015009878011354022108661461024768
p = 30531851861994333252675935111487950694414332763909083514133769861350960895076504687261369815735742549428789138300843082086550059082835141454526618160634109969195486322015775943030060449557090064811940139431735209185996454739163555910726493597222646855506445602953689527405362207926990442391705014604777038685880527537489845359101552442292804398472642356609304810680731556542002301547846635101455995732584071355903010856718680732337369128498655255277003643669031694516851390505923416710601212618443109844041514942401969629158975457079026906304328749039997262960301209158175920051890620947063936347307238412281568760161
Tonelli-shanks 알고리즘은 다음과 같이 사용할 수 이다. 직접 구현하려면 꽤나 복잡하다..
from sympy import *
a = 8479994658316772151941616510097127087554541274812435112009425778595495359700244470400642403747058566807127814165396640215844192327900454116257979487432016769329970767046735091249898678088061634796559556704959846424131820416048436501387617211770124292793308079214153179977624440438616958575058361193975686620046439877308339989295604537867493683872778843921771307305602776398786978353866231661453376056771972069776398999013769588936194859344941268223184197231368887060609212875507518936172060702209557124430477137421847130682601666968691651447236917018634902407704797328509461854842432015009878011354022108661461024768
p = 30531851861994333252675935111487950694414332763909083514133769861350960895076504687261369815735742549428789138300843082086550059082835141454526618160634109969195486322015775943030060449557090064811940139431735209185996454739163555910726493597222646855506445602953689527405362207926990442391705014604777038685880527537489845359101552442292804398472642356609304810680731556542002301547846635101455995732584071355903010856718680732337369128498655255277003643669031694516851390505923416710601212618443109844041514942401969629158975457079026906304328749039997262960301209158175920051890620947063936347307238412281568760161
print(sqrt_mod(a, p))
2362339307683048638327773298580489298932137505520500388338271052053734747862351779647314176817953359071871560041125289919247146074907151612762640868199621186559522068338032600991311882224016021222672243139362180461232646732465848840425458257930887856583379600967761738596782877851318489355679822813155123045705285112099448146426755110160002515592418850432103641815811071548456284263507805589445073657565381850521367969675699760755310784623577076440037747681760302434924932113640061738777601194622244192758024180853916244427254065441962557282572849162772740798989647948645207349737457445440405057156897508368531939120
Chinese Remainder Theorem
중국인의 나머지 정리는, 다음과 같이 주어진 합등식에 대해 유일한 해를 구하게 해주는 방법이다.
$$\begin{align*}
x & \equiv a_1 \mod n_1 \\
x & \equiv a_2 \mod n_2 \\
& \vdots \\
x & \equiv a_n \mod n_n
\end{align*}$$
중국인의 나머지정리는 위의 합등식을 만족하는 유일한 해인 $x$가 있다는것을 증명해준다. $ x \equiv a \mod N \quad \text{where} \quad N = n_1 \cdot n_2 \cdots n_n$ 자세한 내용은 이전에 다루었던글을 참고하자.
2024.09.29 - [BOJ/이론] - 중국인의 나머지 정리(Chinese Remainder Theorem, CRT)
중국인의 나머지 정리(Chinese Remainder Theorem, CRT)
알고리즘이나 정수론, 암호학을 공부하면 항상 등장하는 개념인 중국인의 나머지 정리에 대해 알아볼 것이다.중국인의 나머지 정리란?중국인의 나머지 정리는 다음과 같은 여러 선형 합동
nivr4y.tistory.com
def chinese_remainder_theorem(n, a):
n.sort()
max = n[-1]
a3 = a[-1]
for i in range(len(n)-2, -1, -1):
for j in range(n[i]):
if (max * j + a3) % n[i] == a[i]:
a3 = max*j + a3
max = n[i]*max
break
return a3,max
n = [5,11,17]
a = [2,3,5]
print(chinese_remainder_theorem(n,a))
872
Adrien's Signs
Adrien이 빼기 기호와 기호(르장드르 기호 말하는듯)을 사용해 그의 메세지를 암호화했다고 한다. sourse.py와 output.txt가 주어진다.
# output.txt : [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]
from random import randint
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에서 한글자씩 2진수로 바꾸고 8자리로 채워서 plaintext에 저장한다. 1~p중에 무작위 정수를 뽑은 후, $a^e\mod p$ 의 결과를 n에 저장한다. plaintext(2진수)를 한자리씩 읽으면서 1이면 $a^e\mod p$ 그대로 append하고, 0이면 $-a^e\mod p$를 append한다.
문제를 풀때 뭐부터 해야할지 모르고 있다가 일단 문제에서 르장드르 기호를 쓰라고 힌트를 줬으니 a가 p의 이차 잉여인지 확인해봤다. $p\equiv 3\mod 4$이므로, 르장드르 기호를 적용할 수 있고, $ a^{\frac{p-1}{2}} \equiv 1\mod p$이었다. 여기서 중요한것은, 이차 잉여랑 이차 잉여랑 곱한 결과도 이차 잉여라는 것이다. 즉 $ a^{\frac{p-1}{2}} \mod p$가 이차 잉여니까 $a^e\mod p$ 또한 이차 잉여이기 때문에 값이 1이 된다. $-a^e\mod p$는 -1이 되므로 $= (-1)^{\frac{p - 1}{2}}$를 해보면 -1이 나온다.
결국, b가 1일때는 이차 잉여를, 0일때는 이차 비잉여를 append한 것이다. 르장드르 기호를 사용해서 output.txt에 있는 숫자들의 이차 잉여 여부를 판단해서 원래의 binary를 복구할 수 있을 것이다.
from Crypto.Util.number import *
en = [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
def is_re(a,p):
return pow(a,(p-1)//2, p)
d = ''
for i in en:
if is_re(i,p)==1:
d += '1'
else:
d += '0'
print(long_to_bytes(int(d,2)))
crypto{p4tterns_1n_re5idu3s}
Modular Binomals
소수 $p,q$를 구하기 위해 다음 방정식을 사용하라고 한다.
$$ N = p \cdot q \\
c_1 = (2 \cdot p + 3 \cdot q)^{e_1} \mod N \\
c_2 = (5 \cdot p + 7 \cdot q)^{e_2} \mod N $$
어떻게 할지 모르겠어서 구글링을 해보다가, 재미있는 공식을 발견했다. 1학년의 꿈(Freshman's Dream)이라고 하는 등식인데,
$$ (x+y)^n = x^n + y^n$$
위와 같은 등식이 특정 조건에서 성립하는데, 문제의 상황이 바로 이런 조건이다.
$$ (p+q)^n \mod n = p^n + nC1 \, p^{n-1} q + nC2 \, p^{n-2} q^2 + \cdots + nC(n-1) \, p \, q^{n-1} + q^n $$
이런 식으로 나타나는데, 처음과 마지막의 $ p^n $과$ q^n$을 제외한 중간의 항들은 p,q를 둘다 가지고 있으므로, 법 N에 대해여 0일 수 밖에 없다.
이제 주어진 식을 다음과 같이 변형할 수 있다.
$$ c_1 = (2p)^{e_1}+(3q)^{e_1} \bmod N \\
c_2 = (5p)^{e_2} + (7q)^{e_2} \bmod N $$
미지수가 2개인 연립 방정식을 풀듯이 미지수 하나를 소거해주자.
$$ c_1^{e_2} \equiv (2p)^{e_1e_2} + (3q)^{e_1e_2} \bmod N \\ c_2^{e_1} \equiv (5p)^{e_1e_2} + (7q)^{e_1e_2} \bmod N $$
다음과 같이 정리할 수 있다.
$$ 5^{e_1e_2}c_1^{e_2} -2^{e_1e_2}c_2^{e_1} \equiv (15^{e_1e_2}-14^{e_1e_2})q^{e_1e_2} \bmod N $$
이렇게 구한 $5^{e_1e_2}c_1^{e_2} -2^{e_1e_2}c_2^{e_1} $과 N의 최대공약수를 구한다면, 공통인수가 q 밖에 없을 것이기 때문에 q를 구할 수 있고, q를 구하면 p 또한 구할 수 있다.
import math
N = 14905562257842714057932724129575002825405393502650869767115942606408600343380327866258982402447992564988466588305174271674657844352454543958847568190372446723549627752274442789184236490768272313187410077124234699854724907039770193680822495470532218905083459730998003622926152590597710213127952141056029516116785229504645179830037937222022291571738973603920664929150436463632305664687903244972880062028301085749434688159905768052041207513149370212313943117665914802379158613359049957688563885391972151218676545972118494969247440489763431359679770422939441710783575668679693678435669541781490217731619224470152467768073
e1 = 12886657667389660800780796462970504910193928992888518978200029826975978624718627799215564700096007849924866627154987365059524315097631111242449314835868137
e2 = 12110586673991788415780355139635579057920926864887110308343229256046868242179445444897790171351302575188607117081580121488253540215781625598048021161675697
c1 = 14010729418703228234352465883041270611113735889838753433295478495763409056136734155612156934673988344882629541204985909650433819205298939877837314145082403528055884752079219150739849992921393509593620449489882380176216648401057401569934043087087362272303101549800941212057354903559653373299153430753882035233354304783275982332995766778499425529570008008029401325668301144188970480975565215953953985078281395545902102245755862663621187438677596628109967066418993851632543137353041712721919291521767262678140115188735994447949166616101182806820741928292882642234238450207472914232596747755261325098225968268926580993051
c2 = 14386997138637978860748278986945098648507142864584111124202580365103793165811666987664851210230009375267398957979494066880296418013345006977654742303441030008490816239306394492168516278328851513359596253775965916326353050138738183351643338294802012193721879700283088378587949921991198231956871429805847767716137817313612304833733918657887480468724409753522369325138502059408241232155633806496752350562284794715321835226991147547651155287812485862794935695241612676255374480132722940682140395725089329445356434489384831036205387293760789976615210310436732813848937666608611803196199865435145094486231635966885932646519
q_e1e2 = pow(5,e1*e2,N)*pow(c1,e2,N) - pow(2,e1*e2,N)*pow(c2,e1,N)
q = math.gcd(q_e1e2,N)
print(f'crypto{{{q},{N//q}}}')
crypto{132760587806365301971479157072031448380135765794466787456948786731168095877956875295282661565488242190731593282663694728914945967253173047324353981530949360031535707374701705328450856944598803228299967009004598984671293494375599408764139743217465012770376728876547958852025425539298410751132782632817947101601,112274000169258486390262064441991200608556376127408952701514962644340921899196091557519382763356534106376906489445103255177593594898966250176773605432765983897105047795619470659157057093771407309168345670541418772427807148039207489900810013783673957984006269120652134007689272484517805398390277308001719431273}
crypto의 기초가 되는 MODULAR ARITHMETIC 단원이 끝났다. 그동안 중구난방으로 흩어져있던 지식들을 차근차근 정리해 나가는 느낌이라 좋았고, 처음 보는 어려운 내용도 많았다. 하지만 덕분에 새로운 연산, 개념도 알게 되어서 여기저기 써먹을 수 있을 것 같다. 다음 단원인 SYMMETRIC CRYPTOCRAPHY 또한 열심히 공부해 보자.
'cryptohack.org' 카테고리의 다른 글
[cryptohack.org] INTRODUCTION TO CRYPTOHACK (0) | 2024.09.19 |
---|