[NPUCTF2020]EzRSA
#attachment.py from gmpy2 import lcm , powmod , invert , gcd , mpz from Crypto.Util.number import getPrime from sympy import nextprime from random import randint p = getPrime(1024) q = getPrime(1024) n = p * q gift = lcm(p - 1 , q - 1) e = 54722 flag = b'NPUCTF{******************}' m = int.from_bytes(flag , 'big') c = powmod(m , e , n) print('n: ' , n) print('gift: ' , gift) print('c: ' , c) #n: 17083941230213489700426636484487738282426471494607098847295335339638177583685457921198569105417734668692072727759139358207667248703952436680183153327606147421932365889983347282046439156176685765143620637107347870401946946501620531665573668068349080410807996582297505889946205052879002028936125315312256470583622913646319779125559691270916064588684997382451412747432722966919513413709987353038375477178385125453567111965259721484997156799355617642131569095810304077131053588483057244340742751804935494087687363416921314041547093118565767609667033859583125275322077617576783247853718516166743858265291135353895239981121 #gift: 2135492653776686212553329560560967285303308936825887355911916917454772197960682240149821138177216833586509090969892419775958406087994054585022894165950768427741545736247918410255804894522085720642952579638418483800243368312702566458196708508543635051350999572787188236243275631609875253617015664414032058822919469443284453403064076232765024248435543326597418851751586308514540124571309152787559712950209357825576896132278045112177910266019741013995106579484868768251084453338417115483515132869594712162052362083414163954681306259137057581036657441897428432575924018950961141822554251369262248368899977337886190114104 #c: 3738960639194737957667684143565005503596276451617922474669745529299929395507971435311181578387223323429323286927370576955078618335757508161263585164126047545413028829873269342924092339298957635079736446851837414357757312525158356579607212496060244403765822636515347192211817658170822313646743520831977673861869637519843133863288550058359429455052676323196728280408508614527953057214779165450356577820378810467527006377296194102671360302059901897977339728292345132827184227155061326328585640019916328847372295754472832318258636054663091475801235050657401857262960415898483713074139212596685365780269667500271108538319
可以看到给了 n,p-1和q-1的最最小公倍数gift,密文c
用factordb分解一下试试
发现n果然无法分解,但是p-1和q-1的最最小公倍数gift可以分解
我们可以看到n的长度为2048
gift的长度为2045
因为 gift*gcd((p-1),(q-1))==(p-1)*(q-1) 且 gift%gcd((p-1),(q-1))==0
在因数中长度为3位左右的就是 2**3,测试一下
假设phi=gift*2**3
import sympy import gmpy2 n = 17083941230213489700426636484487738282426471494607098847295335339638177583685457921198569105417734668692072727759139358207667248703952436680183153327606147421932365889983347282046439156176685765143620637107347870401946946501620531665573668068349080410807996582297505889946205052879002028936125315312256470583622913646319779125559691270916064588684997382451412747432722966919513413709987353038375477178385125453567111965259721484997156799355617642131569095810304077131053588483057244340742751804935494087687363416921314041547093118565767609667033859583125275322077617576783247853718516166743858265291135353895239981121 gift = 2135492653776686212553329560560967285303308936825887355911916917454772197960682240149821138177216833586509090969892419775958406087994054585022894165950768427741545736247918410255804894522085720642952579638418483800243368312702566458196708508543635051350999572787188236243275631609875253617015664414032058822919469443284453403064076232765024248435543326597418851751586308514540124571309152787559712950209357825576896132278045112177910266019741013995106579484868768251084453338417115483515132869594712162052362083414163954681306259137057581036657441897428432575924018950961141822554251369262248368899977337886190114104 x = sympy.Symbol('x') y = sympy.Symbol('y') print sympy.solve([x*y-n,(x-1)*(y-1)-gift*8],[x,y]) p,q = sympy.solve([x*y-n,(x-1)*(y-1)-gift*8],[x,y])[0] p,q = int(p),int(q) assert p*q==n assert gift == gmpy2.lcm(p - 1 , q - 1)
可以看到p和q是正确的。
接下来就是正常的解RSA
但是发现一个问题,gcd(e,phi)==2
d = gmpy2.invert(e/2,(p - 1)*(q - 1)) m_mid = pow(c,d,n)
然后对m_mid进行开方,发现爆破不出来,应该是flag太长了。
只能用rabin了
import sympy import gmpy2 n = 17083941230213489700426636484487738282426471494607098847295335339638177583685457921198569105417734668692072727759139358207667248703952436680183153327606147421932365889983347282046439156176685765143620637107347870401946946501620531665573668068349080410807996582297505889946205052879002028936125315312256470583622913646319779125559691270916064588684997382451412747432722966919513413709987353038375477178385125453567111965259721484997156799355617642131569095810304077131053588483057244340742751804935494087687363416921314041547093118565767609667033859583125275322077617576783247853718516166743858265291135353895239981121 gift = 2135492653776686212553329560560967285303308936825887355911916917454772197960682240149821138177216833586509090969892419775958406087994054585022894165950768427741545736247918410255804894522085720642952579638418483800243368312702566458196708508543635051350999572787188236243275631609875253617015664414032058822919469443284453403064076232765024248435543326597418851751586308514540124571309152787559712950209357825576896132278045112177910266019741013995106579484868768251084453338417115483515132869594712162052362083414163954681306259137057581036657441897428432575924018950961141822554251369262248368899977337886190114104 x = sympy.Symbol('x') y = sympy.Symbol('y') print sympy.solve([x*y-n,(x-1)*(y-1)-gift*8],[x,y]) p,q = sympy.solve([x*y-n,(x-1)*(y-1)-gift*8],[x,y])[0] p,q = int(p),int(q) assert p*q==n assert gift == gmpy2.lcm(p - 1 , q - 1) c = 3738960639194737957667684143565005503596276451617922474669745529299929395507971435311181578387223323429323286927370576955078618335757508161263585164126047545413028829873269342924092339298957635079736446851837414357757312525158356579607212496060244403765822636515347192211817658170822313646743520831977673861869637519843133863288550058359429455052676323196728280408508614527953057214779165450356577820378810467527006377296194102671360302059901897977339728292345132827184227155061326328585640019916328847372295754472832318258636054663091475801235050657401857262960415898483713074139212596685365780269667500271108538319 e = 54722 d = gmpy2.invert(e/2,(p - 1)*(q - 1)) m_mid = pow(c,d,n) print m_mid # Euler's criterion def legendre_symbol(a, p): symbol = pow(a, (p - 1) // 2, p) if symbol == p - 1: return -1 return symbol def sqrt_mod(a, p): if a == 0 or legendre_symbol(a, p) != 1: return 0 if p % 4 == 3: return pow(a, (p + 1) // 4, p) if p % 8 == 5: if pow(a, (p - 1) // 4, p) == 1: return pow(a, (p + 3) // 8, p) else: return (pow(2, (p - 1) // 4, p) * pow(a, (p + 3) // 8, p)) % p q = p - 1 s = 0 while q & 1 == 0: q >>= 1 s += 1 z = 2 while legendre_symbol(z, p) != -1: z += 1 m = s c = pow(z, q, p) t = pow(a, q, p) r = pow(a, (q + 1) // 2, p) while t != 1: t2 = t i = 0 while t2 != 1 and i < m: t2 = pow(t2, 2, p) i += 1 b = pow(c, 2 ** (m - i - 1), p) m = i c = (b * b) % p t = (t * c) % p r = (r * b) % p return r r = sqrt_mod(m_mid, p) s = sqrt_mod(m_mid, q) a = gmpy2.invert(p, q) b = gmpy2.invert(q, p) x = (a*p*s+b*q*r) % n y = (a*p*s-b*q*r) % n from Crypto.Util.number import * print repr(long_to_bytes(x % n)) print repr(long_to_bytes((-x) % n)) print repr(long_to_bytes(y % n)) print repr(long_to_bytes((-y) % n))
得到flag