Skip to content

Attack on small primes (p & q)

Introduction

d (private exponent) can be calculated very easily if you know φ(n). To calculate φ(n), you need to find the two prime factors p and q.

$$ n = p * q $$ $$ \varphi(n) = \varphi(pq) = (p - 1)(q - 1) $$ $$ d * e \equiv 1 [\varphi(n))] $$

If n is small (< 256 bits) you can bruteforce p and q, or you can use a well-known database like factordb which contains a lot of factors.

Example

The victim generates a pubKey(n, e) and a privKey(n, d), then encrypt a secret message.

Source code :

from binascii import hexlify

m = int(hexlify(b"s3cr3t"), 16)

p, q = 5484631, 50601277
n = p * q
e = 65537

c = pow(m, e, n)

print("m =", m)
print("n =", n)
print("Encrypted =", c)

Output :

m = 126664548954996
n = 277529332473787
Encrypted = 189766109539025

The attacker only have access to the victim's pubKey(n, e). He will try to recover the victim's privKey(n, d) by factoring n with the help of factordb.

Source code :

from Crypto.Util.number import long_to_bytes
from factordb.factordb import FactorDB
# python3 -m pip install pycryptodome factordb-python


f = FactorDB(n)
f.connect()
factors = f.get_factor_from_api()

p, q = int(factors[0][0]), int(factors[1][0])
phi_n = (p - 1) * (q - 1)
d = pow(e, -1, phi_n)
m = pow(c, d, n)

print("p =", p, ", q =", q)
print("phi(n) =", phi_n)
print("d =", d)
print("m =", long_to_bytes(m))

Output :

p = 5484631 , q = 50601277
phi(n) = 277529276387880
d = 173465855145593
m = b's3cr3t'

The attacker successfully recovers the privKey(n, d) and the plaintext message.