Smooth Numbers & Constructing Smooth Primes
- •
What it is
- •
A "smooth" number is one whose prime factorization consists entirely of small primes (below some chosen bound, called the smoothness bound). Smoothness matters throughout cryptanalysis because many hard-problem algorithms secretly become easy when a relevant number turns out to be smooth: Pohlig-Hellman needs a smooth group order, Pollard's p-1 factorization method needs one prime factor of a target to be -smooth, index calculus / ECM factoring lean on smoothness too, and Arnault-style strong-pseudoprime construction needs several related primes built around smooth structure. Offensively, when an attacker gets to choose a modulus themselves (e.g. because a protocol accepts caller-supplied Diffie-Hellman parameters), they can deliberately construct one that's smooth — real, prime, and outwardly unremarkable, but secretly weak.
- •
- •
When to apply
- •
You control (or want to construct) a modulus for use in an attack that specifically needs a smooth group order — most commonly, setting up a target for Pohlig-Hellman, or (in a very different context) constructing smooth-adjacent primes to defeat a fixed-basis Miller-Rabin check.
- •
- •
Symbols and assumptions
- •
An integer is -smooth if all its prime factors are at most . For DLP, the important smooth integer is the group order, such as , not the prime modulus itself.
- •
- •
Math — step by step
- •
- Construct a candidate group order as a product of small primes and powers. Then test for primality.
- •
- If is prime, has known smooth order . The base may generate a smaller subgroup, so determine its actual order before solving a DLP.
- •
- Not every is prime; vary the factor choices and retest. This constructs a prime with smooth , not a large prime that itself has small prime factors.
- •
- •
- •
Python
- •
def build_smooth_prime(min_bits, small_primes): v, i = 1, 0 while v.bit_length() < min_bits: v *= small_primes[i % len(small_primes)] i += 1 p = v + 1 while not is_prime(p): v *= small_primes[i % len(small_primes)] i += 1 p = v + 1 return p, v # p is smooth-order-plus-one; v = p-1 is fully smooth
- •
- •
SageMath
- •
def build_smooth_prime(min_bits, small_primes): v = prod(small_primes) # or build up incrementally as in the Python version while not is_prime(v + 1): v *= next_prime(small_primes[-1]) return v + 1
- •
- •
- •
Cards
- •
Why does an attacker who can choose their own modulus want it to be smooth?
- •
A smooth group order makes Pohlig-Hellman efficient against it, turning an otherwise-hard discrete log problem into a fast one, while the modulus itself can still look like an ordinary large prime.
- •
- •
What's the basic construction strategy for building a smooth prime?
- •
Multiply together small primes until the product reaches the target bit-length, add 1, and test primality — retry with additional small factors if the result isn't prime.
- •
- •