redpwnCTF 2020 Crypto
primimity
This challenges gives us the n
and e
in a RSA encryption. And it tells us that n
consists of 3 1024-bit primes. In this case, we probably can't factor n
with Crypto tools and by checking factordb, there is no entry of n
. So we need to start from the prime-generation python script.
The Script
def prime_gen(): i = getRandomNBitInteger(1024) d = getRandomNBitInteger(8) for _ in range(d): i = find_next_prime(i) p = find_next_prime(i) d = getRandomNBitInteger(8) for _ in range(d): i = find_next_prime(i) q = find_next_prime(i) d = getRandomNBitInteger(8) for _ in range(d): i = find_next_prime(i) r = find_next_prime(i) return (p,q,r)
this is the prime generation function of the script and we can see how it works. First in generates a random 1024 bit integer to form the base of the random generation. Then for three primes, it generates an 8 bit integer and finds the next_integer after the 1024 base integer that many times.
What can we spot here? Like the name suggests, I kind of get of sense of "proximity". This is because all three primes are generated base off one 1024 bit random integer, and the only thing that's different between the three primes are how many times next_prime
is called. An 8 bit integer can be 0-255
which is not that much. So the biggest gap between each prime is 255
primes away.
The Exploit
By knowing that these primes are close to each other, we could just write something that goes around the cube root of n
and check each prime around the range of +-255
primes. This is tedious work so I wrote a script to handle that. We check each prime by n%found_prime == 0
and it's a factor of n, we found a factor of n
. Notice we only need 2 out of 3 primes to find all of them. In my case, I was only able to get 2 primes, but that gives me the third one as well.We know that one is above the cube root and one is below, we could just find the third one by division.
curr = # Cube root of n, skiped to save space for x in range(300): curr=find_prev_prime(curr) posible.append(curr) curr = # Cube root of n, skiped to save space for x in range(300): curr=find_next_prime(curr) posible.append(curr) ans=[] for x in posible: if(n%x==0): ans.append(x) curr = # Cube root of n, skiped to save space for x in range(curr,n): if(new*x==n): ans.append(x) break curr = # Cube root of n, skiped to save space for x in range(curr,n,-1): if(new*x==n): ans.append(x) break print(ans)
I modified the find_next_prime
function to find the previous prime so that we get a range of +-256
. Then we just wait for the primes to get calculated.
The Flag
Finally, we get the three primes we could just do our regular RSA decryption by finding the totient and the modular inverse of e
and phi
from Crypto.Util.number import inverse p,q,r=139926822890670655977195962770726941986198973494425759476822219188316377933161673759394901805855617939978281385708941597117531007973713846772205166659227214187622925135931456526921198848312215276630974951050306344412865900075089120689559331322162952820292429725303619113876104177529039691490258588465409208581,139926822890670655977195962770726941986198973494425759476822219188316377933161673759394901805855617939978281385708941597117531007973713846772205166659227214187622925135931456526921198848312215276630974951050306344412865900075089120689559331322162952820292429725303619113876104177529039691490258588465409397803,139926822890670655977195962770726941986198973494425759476822219188316377933161673759394901805855617939978281385708941597117531007973713846772205166659227214187622925135931456526921198848312215276630974951050306344412865900075089120689559331322162952820292429725303619113876104177529039691490258588465409494847 n=# Deleted to Save Space e=65537 c= # Deleted to Save Space phi = (p-1)*(q-1)*(r-1) d=inverse(e,phi) m=pow(c,d,n) print(hex(m))