Description
In RSA, there is a small danger of using small primes. Can you decrypt this? Given: c, n, e.
Setup
Download the values file from the challenge page.
wget <url>/valuesSolution
Want to try it yourself first?
The guided walkthrough reveals hints one step at a time.
Step 1Factor n
ObservationThe description warns about small primes and hands over n directly. So the modulus is too short to be secure, and a public database like factordb.com will have it factored already.Because n is small (only a few hundred bits), it can be factored instantly using factordb.com. Paste the value of n into the search box to retrieve the two prime factors p and q.Learn more
RSA's security relies entirely on the integer factorization problem: given a large number
n = p * q, it should be computationally infeasible to findpandq. For modern RSA,nis at least 2048 bits (~617 decimal digits), which makes factoring effectively impossible with current technology.However, when
nis small - say, a few hundred bits or fewer - factoring is trivial. Tools like factordb.com maintain a database of pre-factored numbers and can factor small integers instantly. For larger numbers they use algorithms like the Quadratic Sieve or General Number Field Sieve (GNFS). The title "Mind Your Ps and Qs" refers to the prime factorspandq- small primes undermine the entire system.Historical context: In 2012, researchers found that millions of real-world RSA public keys shared prime factors because of weak random number generators used during key generation. By computing GCDs between pairs of public keys, they factored a significant percentage of real keys - a real-world demonstration of exactly this vulnerability.
Step 2Compute the private key and decrypt
ObservationWith p and q recovered, the standard RSA private key formula applies directly: phi is (p-1)(q-1), and d is the modular inverse of e mod phi. Decrypt with pow(c, d, n) and convert the integer to bytes.With p and q known, compute phi = (p-1)*(q-1), then the private exponent d = modular_inverse(e, phi). Raise c to the power d mod n to recover the plaintext integer m, then convert it to bytes.pythonpython3 << 'EOF' from Crypto.Util.number import inverse, long_to_bytes # Fill in values from the challenge file and factordb c = <c> n = <n> e = <e> p = <p> # from factordb.com q = <q> # from factordb.com phi = (p - 1) * (q - 1) d = inverse(e, phi) m = pow(c, d, n) print(long_to_bytes(m).decode()) EOFExpected output
picoCTF{sma11_N_n0_g0od_...}What didn't work first
Tried: Running sympy.factorint() or a local factoring script on n instead of using factordb.com
At this size sympy.factorint and similar trial-division or Pollard-rho implementations may finish, but they can stall for tens of seconds or minutes when the two primes are large without being tiny. factordb.com already stores the factorization, so a lookup is instant and skips the local compute entirely.
Tried: Passing c**d to long_to_bytes without the modular form pow(c, d, n)
Computing c**d as a raw exponentiation builds an astronomically large integer before the mod is ever applied, so Python exhausts memory or runs forever. Three-argument pow(c, d, n) reduces at each squaring step and returns the same answer in milliseconds.
Learn more
The RSA decryption process follows directly from the mathematics. Euler's totient function
φ(n) = (p-1)*(q-1)counts how many integers less thannare coprime with it. The private exponentdis defined as the modular inverse ofemoduloφ(n), meaninge*d ≡ 1 (mod φ(n)). This relationship is what makes decryption the inverse of encryption.Modular exponentiation (
pow(c, d, n)) uses Python's built-in three-argument form, which is highly efficient - it applies the square-and-multiply algorithm internally. Even with a 2048-bit exponent, this completes in milliseconds. Without the three-argument form (computingc**dand then taking mod), the intermediate number would have millions of digits and be completely impractical.The
long_to_bytes()function frompycryptodomeconverts the recovered plaintext integer back to a byte string. RSA operates on integers, so text messages are first converted to integers (using big-endian byte encoding) before encryption.long_to_bytesreverses this step to give the human-readable flag.
Interactive tools
- RSA CalculatorDecrypt RSA ciphertexts, factor n from the sum of primes, or generate key parameters. Handles arbitrarily large BigInt values.
Alternate Solution
Use the RSA Calculator on this site: enter the two primes p and q (recovered from factoring n), the public exponent e, and the ciphertext c. The tool computes d and decrypts the message in the browser - no Python required.
Flag
Reveal flag
picoCTF{sma11_N_n0_g0od_...}
When n is small enough to factor, RSA provides zero security - always use at least 2048-bit keys.