Google CTF – CHUNK NORRIS
题目
下载附件后是两个文件
1 | #!/usr/bin/python3 -u |
1 | n = 0xab802dca026b18251449baece42ba2162bf1f8f5dda60da5f8baef3e5dd49d155c1701a21c2bd5dfee142fd3a240f429878c8d4402f5c4c7f4bc630c74a4d263db3674669a18c9a7f5018c2f32cb4732acf448c95de86fcd6f312287cebff378125f12458932722ca2f1a891f319ec672da65ea03d0e74e7b601a04435598e2994423362ec605ef5968456970cb367f6b6e55f9d713d82f89aca0b633e7643ddb0ec263dc29f0946cfc28ccbf8e65c2da1b67b18a3fbc8cee3305a25841dfa31990f9aab219c85a2149e51dff2ab7e0989a50d988ca9ccdce34892eb27686fa985f96061620e6902e42bdd00d2768b14a9eb39b3feee51e80273d3d4255f6b19 |
Writeup
通过分析线性同余方法生成的随机质数,找到分解n的方法:
首先研究pq的生成,可知
\begin{align} B &= 2 ^ {64}\\ p &= s_1 << 960 + (s_1 * a \% B) << 896 + (s_1 * a^2 \% B) << 832 + ... + (s_1 * a^{14} \% B) << 64 + (s_1 * a^{15} \% B)\\ &= s_1 << 960 + k_1 << 64 + (s_1 * a^{15} \% B)\\ q &= s_2 << 960 + (s_2 * a \% B) << 896 + (s_2 * a^2 \% B) << 832 + ... + (s_2 * a^{14} \% B) << 64 + (s_2 * a^{15} \% B)\\ &= s_2 << 960 + k_2 << 64 + (s_2 * a^{15} \% B)\\ pq &= p * q\\ &= (s_1 << 960 + k_1 << 64 + (s_1 * a^{15} \% B))*(s_2 << 960 + k_2 << 64 + (s_2 * a^{15} \% B))\\ &= s_1s_2 << 1920 + s_1k_2 << 64 + (s_2 * a^{15} \% B)s_1 << 960 + k_1s_2 << 1024 + k_1k_2 << 128 \\ &+ (s_2 * a^{15} \% B)k_1 << 64 + (s_1 * a^{15} \% B)s_2 << 960 + (s_1 * a^{15} \% B)k_2 << 64 + (s_1 * a^{15} \% B)(s_2 * a^{15} \% B)\\ \end{align}
去掉不重叠的位数部分
可知 等于pq的高64位或者其减一(由于进位),等于低64位
因此可计算出的值,分别考虑进位和不进位,可计算出两个值
得到的两个乘积,接下来用yafu分别进行质因数分解
已知s |= 0xc000000000000001
可知s & 0xc000000000000001 != 0
,由于分解后的质因数太多,产生的因数也太多,无法马上确定哪个因数和s匹配,我们利用质因数集生成其所有子集,再借用上式条件和p为质数的条件找到正确的s1和s2
1 | #!/usr/bin/python3 -u |
另一道类似赛题
百越杯赛题 - math
题目
1 | from libnum import * |
以上代码的输出如下:
1 | 37290153165969298170747767487987767106604956327590459309623310884436645867385405226836923826439760402232182199047042298740970941114757402758035338227352981884345194304183079410512904720516197002459598643659802383718137698974557870280366585586392385470235597777672593360788744398375690898546971801388821194234775373952698134335885991694714949974679482564600815766377388895037809222168800554222619940240853717965637149897765149770956991503459995786889995461520332980787566967767243445754450380553166156028030513979079301998632175402072502016282327825403961392784400687386536170117841528456263456021394359662685873080287765689757030352392386374307257266677811647633925457228036341541693812765785784057781251815707260401922647083928541835257244409503393940374048782722357915189148582407507806733352268172024029303953342827905707727300151171157623562387977156106983516547443642151573456682745626175061369310982040554116369983687552560719792717887667637107087090897681039368534492698712183905213300675019880169669159964289135274268951386122314246699412166656323475268623240778461031327966634628420986855022944785421496251349486099392411145566566437986155875600117002222032846697544656901210849382567936904958595228620017066673190455548617917273881089052468844830306632804733848750820391807100094948772492402636422551350516389981409116121666282434777976293668265700614707939438561465158100805697922866599682141928964956895065357677209698826476508887966210560085802544989199042295263908880764987497015388183619829914488242002252489035055312547747792033076017959711401664024465093007341377103124755426567781873434171576297409356302054965976819782564966567852321032108507478998871390301458143582617644492262165902951270805160376459476885522275531457938661136508391452032625051782015102833218959697470722331233350397631435041061401412630047713991858871735035714326218833998760244965866341087147750123869855038366992182962371334384526411144813368418246803652025254206189223834187719880012103660703380187226220860 |
Writeup
\begin{align} p & = a \cdot 10^{500} + b \\ q & = b \cdot 10^{500} + a \\ p \cdot q & = (a \cdot 10^{500} + b) \cdot (b \cdot 10^{500} + a) \\ & = ab \cdot 10^{1000} + (a^2+b^2) \cdot 10^{500} +ab\\ & \end{align}
因为a和b的位数都是500位,由此可知
的有效位数范围为1001~2000
和的有效位数范围是501~1500
的有效位数范围1~500
由此可知
的前500位等于的前500位或其减一
的后500位等于的后500位
的前500位+的后500位等于的中间1001~1500位或其加上
的后500位+的前500位等于的中间501~1000位
根据上述发现可计算出a、b的值,其中利用的值是否为完全平方数判断ab的正确性
1 | from libnum import * |
输出如下:
存在进位
因此存在进位
利用开方求得的值,又已知,再利用一元二次方程的求根公式求出a和b的值
1 | ab = ab_2 |
输出如下:
1 | delta = 28970382423653526230782087428394120199094608888807510969672174008572263444342743452382065495452410979665183590859836472860381842418270886250846330507167646674351905885014449434182842316793842355041032703945358809543746947830533653096857965009150717206961368552309542092906822247898706652989394172510971441082397663739139074168863166474942514453940979697271097233244125249898829123427276166705668136075753341362350636336479869531538499746880132398933374584887892784910782260556527383469248578187483469 |
由于
1 | p = next_prime(p+c) |
假设
\begin{align} p' & = p+c+x \\ q' & = q+c+y \\ \end{align}
则有
\begin{align} n & = p' \cdot q' \\ & = (p+c+x) \cdot (q+c+y)\\ & = c^2+(p+x+q+y)c+(p+x)(q+y)\\ \Delta & = (p+x+q+y)^2-4(p+x)(q+y)+4n \\ \end{align}
显然x、y并不大,可进行爆破,终止条件为是一个完全平方数
1 | n=37290153165969298170747767487987767106604956327590459309623310884436645867385405226836923826439760402232182199047042298740970941114757402758035338227352981884345194304183079410512904720516197002459598643659802383718137698974557870280366585586392385470235597777672593360788744398375690898546971801388821194234775373952698134335885991694714949974679482564600815766377388895037809222168800554222619940240853717965637149897765149770956991503459995786889995461520332980787566967767243445754450380553166156028030513979079301998632175402072502016282327825403961392784400687386536170117841528456263456021394359662685873080287765689757030352392386374307257266677811647633925457228036341541693812765785784057781251815707260401922647083928541835257244409503393940374048782722357915189148582407507806733352268172024029303953342827905707727300151171157623562387977156106983516547443642151573456682745626175061369310982040554116369983687552560719792717887667637107087090897681039368537631451824008445150593322916621649220131918968381060182780056625981084043051299820111816407714077085179863978735943069017108793879580065214612325438873475463670028900700692331942940752758392673078381358679392924527642317471983718497708036815480999969876652686414859011578133113730930542513696962965675847727315009182439824295556392013537952480748938928408290671107333656277905126915134701713932190005567660746756601077906025437341247344713253422720837604831207936303137369977025954243957891577406266667226864293421045998499026349073973676803568161225217742238807019077558158505566968246373749202724739826733649675118977232613022754175080279658222551375134841038576853604493545070340911086664690452703289923302725433846272032435289554345937247024060157309603467510583043117535674355137280615256893616267247008324272285381171004240649782585733382066689782757882726882857063752626302302445421988032917071576855484653938018800413715950664940531918933498765096986757431159488734247146715664409455285656746712809269599736842704425915921 |
输出如下
1 | x, y = 1, 1836 |
用求根公式算出c的值,进而算出p和q的值
1 | x, y = 1, 1836 |
输出如下:
1 | c = 250059412706552500264745576027 |
最后利用RSA解密算法解密
1 | e = 65537 |
b'flag{ddc4205ecd6c22035acae589113bb8aa}'
得到flag{ddc4205ecd6c22035acae589113bb8aa}