Description
Can you factor this small RSA modulus? The challenge provides an X.509 certificate containing a tiny RSA public key. Factor the modulus into its two prime factors p and q - the flag is simply those two numbers.
Setup
Download the PEM-encoded X.509 certificate from the challenge.
wget <url>/certificateSolution
Want to try it yourself first?
The guided walkthrough reveals hints one step at a time.
Step 1
Extract n and e from the certificateObservationI noticed the challenge provides a PEM-encoded X.509 certificate, which meant the RSA public key parameters were embedded inside it and needed to be extracted before any factoring could begin.Parse the PEM certificate with openssl to reveal the RSA modulus (n) and public exponent (e) in human-readable form. The modulus n is only 53 bits - small enough to factor by trial division or using factordb.com. There is no ciphertext in this challenge; the flag is the prime factors themselves.bashopenssl x509 -in cert -text -nooutWhat didn't work first
Tried: Running 'openssl rsa -in cert -text -noout' to read the key from the certificate
The 'openssl rsa' command expects a raw private key file, not a certificate. It will error with 'unable to load Private Key'. The correct command is 'openssl x509' which parses the full X.509 certificate structure and prints the embedded public key modulus under the 'Subject Public Key Info' section.
Tried: Using 'openssl x509 -in cert -pubkey -noout' and expecting to see n and e directly
This flag extracts the raw public key in PEM format, not the parsed modulus and exponent values. You would then need a second command ('openssl rsa -pubin -text -noout') to decode that PEM blob. The single-pass '-text -noout' flag prints n and e in hex directly from the certificate, which is simpler for the next factoring step.
Learn more
RSA security depends on the difficulty of factoring large numbers. For a 2048-bit RSA key, factoring is computationally infeasible. But for small moduli (a few digits to a few hundred digits), factoring is easy using trial division, Pollard's rho algorithm, or pre-computed databases.
factordb.com maintains a database of pre-factored numbers. For CTF challenges, the modulus is usually small enough to be in the database already.
Step 2
Factor n to get p and qObservationI noticed from the openssl output that the modulus n was only 53 bits, which is far too small for secure RSA and suggested that trial division or a factoring database would yield p and q in milliseconds.Factor the modulus n to get the two prime factors p and q. Use Python, factordb, or an online factoring service.pythonpython3 << 'EOF' # Small n can be factored by trial division import math n = <PASTE_N_HERE> # Trial division for p in range(2, int(math.isqrt(n)) + 1): if n % p == 0: q = n // p print(f"p = {p}") print(f"q = {q}") break EOFExpected output
p = 67867967 q = 73176001
What didn't work first
Tried: Pasting n into a general-purpose integer factoring site like WolframAlpha instead of factordb.com
WolframAlpha can factor small integers but times out or refuses computation for numbers even a few dozen bits larger than this modulus. factordb.com is purpose-built for this task and pre-stores results, so it returns factors instantly regardless of size within CTF range. If WolframAlpha shows 'integer factorization not computed', switch to factordb.
Tried: Running the trial division loop without first replacing PASTE_N_HERE with the actual modulus value from the openssl output
The script uses a placeholder token that Python will fail to parse as an integer, raising a SyntaxError. You must copy the modulus hex string from the openssl output, convert it to a Python integer (using int('hex_digits', 16)), and substitute that value in place of PASTE_N_HERE before running the script.
Learn more
Why "John Pollard". The challenge name names John M. Pollard, who designed two of the classic factoring algorithms: Pollard's rho (1975) and Pollard's p-1 (1974). Trial division costs
O(sqrt(n)); Pollard's rho costs aboutO(n^(1/4)); both crush small CTF moduli in milliseconds.Pollard's rho intuition. Iterate
x_(i+1) = x_i^2 + 1 (mod n). By the birthday paradox, after aboutsqrt(p)steps two values collide modulo the smallest prime factorp, even though they have not collided modulon. Floyd's tortoise-and-hare detects this collision: at every step computeg = gcd(|x - y|, n)withymoving twice as fast. When1 < g < n,gis a non-trivial factor.def pollard_rho(n): x = y = 2 g = 1 while g == 1: x = (x*x + 1) % n y = (y*y + 1) % n y = (y*y + 1) % n # tortoise vs hare g = math.gcd(abs(x - y), n) return g if g != n else None # retry with new f if g == nWorked toy example. Factor
n = 8051:step x y gcd(|x-y|, 8051) 1 5 26 1 2 26 7474 1 3 677 871 1 4 7474 1244 83 <- factor! 8051 = 83 * 97 (both prime)Pollard's p-1. Different family of attack: works when
p - 1is "B-smooth" (only small prime factors). Computea = 2^(B!) mod nfor a chosen boundB; ifp - 1 | B!then Fermat's little theorem gives2^(B!) ≡ 1 (mod p), sogcd(a - 1, n) = p. This is why prime-generation libraries pick safe primes wherep = 2q + 1withqalso prime - that makesp - 1have a giant prime factor and defeats p-1.Database lookup. For competition speed, paste
nintofactordb.com. The database stores millions of pre-factored RSA challenge numbers, including most CTF moduli that have appeared online. If FactorDB returnsFF (Fully Factored), you havep, qinstantly.Step 3
Submit p and q as the flagObservationI noticed the challenge description stated the flag is just the two prime factors, so once p and q were recovered from factoring n, no decryption step was needed and the flag format picoCTF{p,q} followed directly.Once you have factored n into p and q, the flag is simply picoCTF{p,q}. No decryption step is needed - the challenge tests only whether you can break the key itself, not use it.Learn more
Why the flag is just p and q. This challenge tests one specific RSA weakness: using a modulus that is too small to be secure. The attacker goal is to factor
nintopandq. Recovering those factors proves the key is broken - there is no separate encrypted message to recover.Flag format. Enter
picoCTF{p,q}wherepandqare the two prime factors in either order. For this certificate the factors are73176001and67867967, so the flag ispicoCTF{73176001,67867967}.
Interactive tools
- RSA CalculatorDecrypt RSA ciphertexts, factor n from the sum of primes, or generate key parameters. Handles arbitrarily large BigInt values.
Alternate Solution
Instead of trial division in Python, paste the modulus into factordb.com. The database has the factors pre-computed, so you get p and q instantly without writing any code. Then form the flag as picoCTF{p,q}.
Flag
Reveal flag
picoCTF{73176001,67867967}
The flag is the two prime factors of the certificate modulus. No decryption step is required.