當中國剩餘定理邂逅RSA
前言
實在不知道起什麼標題,於是滑稽了一波。寫這篇文章的起源是2018高校網路資訊保安管理運維挑戰賽的一道RSA題目,藉此機會,將中國剩餘定理與RSA的結合研究一下。
題目描述
拿到題目很簡短
身陷囹圄
發現
assert gcd(e1,(p1-1)*(q1-1))==14 assert gcd(e2,(p2-1)*(q2-1))==14
那麼本能想到公約數的問題,於是嘗試
gcd(n1,n2)
發現有公約數
那麼可以分解出p和q1,q2
p = gcd(n1,n2) q1 = n1/p q2 = n2/p
得到結果
p=12120327527644543811107783655014863098833219936714394976342507913322405566177432644931575840816861543106701611662013978324877080018872656490603706071067111 q1=12037827528067911684278967221392433256129944002157200272548317200308481572950474775891360447285969682243206009995242277136633522897723532096467191105943909 q2=12301580698247665838432962460247894405698817646605188562297985838079356879336309758823376086396761749681729993573203954506346863479448531269351981555913253
到目前為止一直很開心,因為成功的分解了p和q
那麼是不是直接求逆元,得到私鑰,就結束了呢?
我開心的執行
print gmpy2.invert(e,phi)
直到報錯,我才想起來
gcd(e,phi)=14
所以直接求逆元肯定是不行的
第一時間想到的是Rabin Attack,但是那是e=2的時候,所以此時陷入困境
公式代換
後來想到等式代換
我們知道b=14,此時a和phi(n)互素
那麼可以求a和phi的逆元得到bd
gmpy2.invert(a,phi)
於是可以
pow(c,bd,n)
得到m^14 mod n1的值,於是同理:
n1得到一組m^14 mod n1的值
n2得到一組m^14 mod n2的值
可以得到以下方程組:
如果這裡不是m^14,是m^2或者m^3
那麼完全可以嘗試爆破得到m
因為m^2不會太大,所以
那麼完全可以使用低指數的思想去破解
然而這裡是m^14,並不是啥低指數了。
中國剩餘定理
雖然題目走的絕,但是他給了2組等式,那麼這樣的等式,僅僅為了讓我們利用公約數分解p,q這麼簡單嗎?答案顯然是否定的
這裡我們可以嘗試中國剩餘定理
二者聯立,可以求出m的特值,但是這裡的m值並不是真的flag的明文
因為m^14足夠大,這裡僅僅是個模數,可以理解為
flag=m+k*n1
依舊需要爆破k,如果flag的長度比較短,例如
flag={this_is_flag}
那麼很快可以爆破出來,但是事實上,題目的格式都是
EIS{MD5(…..)}
估計一時半會兒出不來了
靈感乍現
在非常難受的情況下,學長給了我一些點播,我們剛才的做法,完全是對中國剩餘定理使用的浪費,我們可以根據中國剩餘定理得到如下3個式子
即模數分解,這樣依舊可以計算出特解m
之前我們到這裡為止,開始了爆破,無果而終。
那之前為什麼我們不把現在這個局面當做
這樣一個問題去解決呢?
這裡的c我們已經求得,n1也是已知的,並且可以被分解,公鑰e=14
因為這樣無濟於事,e依舊和phi(n1)有公約數。
那有沒有辦法換個模數呢,讓phi與e互素
這裡就是這道題的有趣之處:
我們可以將後2個式子合併
(注:為什麼可以合併呢?)
我們可以這樣理解
兩邊同時模q1q2,即可得到合併後結果
所以我們現在有等式
我們可以把他當做一個新的RSA題目:
密文等於中國剩餘定理求出的m特解 公鑰等於14 模數已經分解為q1和q2
水到渠成
那麼這樣一看,就是一個非常簡單的RSA題目了
c=1157918953656051452784355699923609238578087085530356730257378716186056416448726997740518977363905297393271755641099448971883212306481009956454341821281132105675527179275608942496622728690548474209986204730278844220750782548612807173412632486533313585094360198798935868257031751209954691446183447044165077233401610378901936945171131038402147803394967428713339276583596523854139656861116867477243532939513114104962464919267716378905965731491698192883615068033313579 q1=12037827528067911684278967221392433256129944002157200272548317200308481572950474775891360447285969682243206009995242277136633522897723532096467191105943909 q2=12301580698247665838432962460247894405698817646605188562297985838079356879336309758823376086396761749681729993573203954506346863479448531269351981555913253 e=14
當我們興致勃勃去求逆元私鑰d時,又發現
這裡的e和phi又不是互素的,有公約數2,乍一看非常頭疼
實際上,這裡的公約數2和14比實在太小了,所以我們可以直接破解:
按照之前的思路
2d可以通過7的逆元求得,由於2次方太小,所以直接對m開方即可
完整指令碼如下
n1=0xcfc59d54b4b2e9ab1b5d90920ae88f430d39fee60d18dddbc623d15aae645e4e50db1c07a02d472b2eebb075a547618e1154a15b1657fbf66ed7e714d23ac70bdfba4c809bbb1e27687163cb09258a07ab2533568192e29a3b8e31a5de886050b28b3ed58e81952487714dd7ae012708db30eaf007620cdeb34f150836a4b723L e1=0xfae3aL c1=0x81523a330fb15125b6184e4461dadac7601340960840c5213b67a788c84aecfcdc3caf0bf3e27e4c95bb3c154db7055376981972b1565c22c100c47f3fa1dd2994e56090067b4e66f1c3905f9f780145cdf8d0fea88a45bae5113da37c8879c9cdb8ee9a55892bac3bae11fbbabcba0626163d0e2e12c04d99f4eeba5071cbeaL n2=0xd45304b186dc82e40bd387afc831c32a4c7ba514a64ae051b62f483f27951065a6a04a030d285bdc1cb457b24c2f8701f574094d46d8de37b5a6d55356d1d368b89e16fa71b6603bd037c7f329a3096ce903937bb0c4f112a678c88fd5d84016f745b8281aea8fd5bcc28b68c293e4ef4a62a62e478a8b6cd46f3da73fa34c63L e2=0x1f9eaeL c2=0x4d7ceaadf5e662ab2e0149a8d18a4777b4cd4a7712ab825cf913206c325e6abb88954ebc37b2bda19aed16c5938ac43f43966e96a86913129e38c853ecd4ebc89e806f823ffb802e3ddef0ac6c5ba078d3983393a91cd7a1b59660d47d2045c03ff529c341f3ed994235a68c57f8195f75d61fc8cac37e936d9a6b75c4bd2347L from libnum import * import gmpy2 p=gcd(n1,n2) q1=n1/p q2=n2/p assert(p*q1==n1) assert(p*q2==n2) f1=(p-1)*(q1-1) f2=(p-1)*(q2-1) tmp=gcd(e1,e2) e1=e1/tmp e2=e2/tmp d1=invmod(e1,f1) d2=invmod(e2,f2) m1=pow(c1,d1,n1) m2=pow(c2,d2,n2) m3=m1%p m2=m2%q2 m1=m1%q1 m=solve_crt([m1,m2,m3], [q1,q2,p]) print m n=q1*q2 f=(q1-1)*(q2-1) m=m%n d=invmod(7,f) m=pow(m,d,n) print n2s(gmpy2.iroot(m, 2)[0])
後記
當我們的公鑰與phi不互素時,不僅有Rabin Attack解法了,這道題對中國剩餘定理的靈活運用非常有趣XD