RSA已知p高位
from Crypto.Util.number import getPrime, bytes_to_long from secret import flag p = getPrime(1024) q = getPrime(1024) n = p * q e = 65537 hint1 = p >> 724 hint2 = q % (2 ** 265) ct = pow(bytes_to_long(flag), e, n) print(hint1) print(hint2) print(n) print(ct)
题目如上,由hint1可知p的低724位丢失,而q的高位丢失到只剩下低位265位,因为q%(2**256)后得到的余数一定小于2**265,而2**265对应的二进制就是265位。
提取出的数学式子就是$q_{0}\equiv q(mod\,2^{265})\Rightarrow n\equiv pq_{0}(mod\,2^{265})$
则$q_{0}^{-1}n\equiv p(mod\,2^{265})$
令$p_{0}\equiv p(mod\,2^{265})$
则$p_{0}\equiv q_{0}^{-1}n(mod\,2^{265})$
而$q_{0}$的逆为$q_{0}q_{0}^{-1}\equiv1(mod\,2^{265})$
sage代码如下:
from Crypto.Util.number import long_to_bytes h1 = 1514296530850131082973956029074258536069144071110652176122006763622293335057110441067910479 h2 = 40812438243894343296354573724131194431453023461572200856406939246297219541329623 n = 21815431662065695412834116602474344081782093119269423403335882867255834302242945742413692949886248581138784199165404321893594820375775454774521554409598568793217997859258282700084148322905405227238617443766062207618899209593375881728671746850745598576485323702483634599597393910908142659231071532803602701147251570567032402848145462183405098097523810358199597631612616833723150146418889589492395974359466777040500971885443881359700735149623177757865032984744576285054725506299888069904106805731600019058631951255795316571242969336763938805465676269140733371287244624066632153110685509892188900004952700111937292221969 c = 19073695285772829730103928222962723784199491145730661021332365516942301513989932980896145664842527253998170902799883262567366661277268801440634319694884564820420852947935710798269700777126717746701065483129644585829522353341718916661536894041337878440111845645200627940640539279744348235772441988748977191513786620459922039153862250137904894008551515928486867493608757307981955335488977402307933930592035163126858060189156114410872337004784951228340994743202032248681976932591575016798640429231399974090325134545852080425047146251781339862753527319093938929691759486362536986249207187765947926921267520150073408188188 e = 0x10001 mod = 1<<265#即2^265 pl = n*inverse_mod(h2, mod) % mod pbar = (h1 << 724) + pl
至此可以算出p的低265位,还有724-265=459位未知,但是coppersmith定理至少要求未知位数小于454,所以还有5位未知,可以爆破
完整sage代码如下:
from Crypto.Util.number import long_to_bytes h1 = 1514296530850131082973956029074258536069144071110652176122006763622293335057110441067910479 h2 = 40812438243894343296354573724131194431453023461572200856406939246297219541329623 n = 21815431662065695412834116602474344081782093119269423403335882867255834302242945742413692949886248581138784199165404321893594820375775454774521554409598568793217997859258282700084148322905405227238617443766062207618899209593375881728671746850745598576485323702483634599597393910908142659231071532803602701147251570567032402848145462183405098097523810358199597631612616833723150146418889589492395974359466777040500971885443881359700735149623177757865032984744576285054725506299888069904106805731600019058631951255795316571242969336763938805465676269140733371287244624066632153110685509892188900004952700111937292221969 c = 19073695285772829730103928222962723784199491145730661021332365516942301513989932980896145664842527253998170902799883262567366661277268801440634319694884564820420852947935710798269700777126717746701065483129644585829522353341718916661536894041337878440111845645200627940640539279744348235772441988748977191513786620459922039153862250137904894008551515928486867493608757307981955335488977402307933930592035163126858060189156114410872337004784951228340994743202032248681976932591575016798640429231399974090325134545852080425047146251781339862753527319093938929691759486362536986249207187765947926921267520150073408188188 e = 0x10001 mod = 2**265 pl = n*inverse_mod(h2, mod) % mod pbar = (h1 << 724) + pl PR.<x> = PolynomialRing(Zmod(n)) for i in range(64): f = pbar + (x*mod*64) + (i<<265) f = f.monic() pp = f.small_roots(X=2^453, beta=0.4) if pp: break p = int(pbar + (pp[0]<<271) + (i<<265)) q = n // p d = inverse_mod(e, (p-1)*(q-1)) print(long_to_bytes(power_mod(c, d, n)))