Baby-Step Giant-Step — the generic meet-in-the-middle solver for a mid-sized discrete log
Baby-Step Giant-Step (BSGS) is the generic O(sqrt(n)) meet-in-the-middle algorithm for g^x = h in any group of order n — it needs no special structure, only that you can multiply and compare group elements.
The signal that gives it away
- You have g, h, and a modulus or curve, and the task is "recover the exponent/scalar" — a discrete-log shape, not a factoring one.
- The group order `n` (or the order of the relevant subgroup) is medium-sized: roughly up to 2^40–2^48. Below that, brute force is pointless to bother avoiding; above that, sqrt(n) no longer fits in memory/time and BSGS alone stops being the answer.
- It doesn't matter which group: F_p^*, an elliptic curve, even permutation groups — BSGS is agnostic to the algebra, it only cares about the *order*.
- It's frequently not the final step but a sub-routine: inside Pohlig-Hellman — solving the discrete log when the group order is smooth, once the group order is factored into small prime-power pieces, each piece's mini-DLP (order p_i^{e_i}) is exactly the size BSGS is good at. Seeing "smooth order, but with one prime-power factor still too big for brute force" is a strong signal to reach for BSGS *inside* Pohlig-Hellman, not instead of it.
How to exploit it
1. Establish the working order n — reduce to g's actual subgroup order, not blindly p-1 (or the curve's group order), since the real order is often much smaller and that's what should size m.
2. Decompose the unknown exponent as x = i*m + j with m = ceil(sqrt(n)).
3. Baby steps: precompute a hash table {g^j : j} for j in [0, m). This is the memory-heavy part — O(sqrt(n)) entries.
4. Giant steps: compute factor = g^(-m), then walk gamma = h, h*factor, h*factor^2, ... — on each step check the table for a hit; a hit at giant-step i and baby-step j gives x = i*m + j.
5. Always verify g^x == h before trusting the result — cheap check, catches subgroup/order mistakes early.
``python
from sage.all import Integer
def bsgs(g, h, n):
m = Integer(n).isqrt() + 1
tbl = {}; e = g**0
for j in range(m): tbl[e] = j; e *= g
fac = g**(-m); gamma = h
for i in range(m):
if gamma in tbl: return i*m + tbl[gamma]
gamma *= fac
``
In practice, don't hand-roll this against a real challenge unless you need the tuning control: Sage's discrete_log(h, g, ord=n) auto-selects BSGS/Pohlig-Hellman/etc. and is faster to get right under time pressure. Reach for the manual version when you need to plug it in as the per-prime-power solver inside a hand-built Pohlig-Hellman loop, or when you need the memory/time tradeoff explicitly (see below).
What does NOT work
- Running BSGS on the full group order when the order is smooth. If n = p-1 (or the curve order) factors into small primes, BSGS on the whole n wastes time and memory that Pohlig-Hellman — solving the discrete log when the group order is smooth would spend far more efficiently — factor the order first, *then* decide whether BSGS is even needed per-factor.
- Assuming O(sqrt(n)) is "small enough" without checking memory. The table is O(sqrt(n)) *entries*, not O(sqrt(n)) *time only* — at the upper end of the practical range (order approaching 2^48+) the table itself won't fit in memory even though the time bound looks tractable on paper. That's the actual ceiling, not raw CPU time.
- Sticking with BSGS when memory, not time, is the bottleneck. If the table won't fit, switching to Pollard's rho for logarithms gives about the same O(sqrt(n)) time with only O(1) memory — a straight substitution, not a different strategy. Don't try to "optimize" BSGS's memory footprint by hand when the rho algorithm already solves that tradeoff.
- Skipping the order reduction. Using the full modulus order instead of g's actual (possibly much smaller) subgroup order inflates m for no reason and can make an otherwise-tractable instance look too big to attempt.
- Trusting a hit without the `g^x == h` check. Hash collisions or an off-by-one in the i*m + j bookkeeping produce a wrong-looking-right answer; the verification step is one line and is the difference between a fast win and chasing a subtly wrong exponent.
Related
Discrete Logarithm — the factorization of the group order picks your algorithm Pohlig-Hellman — solving the discrete log when the group order is smooth Index Calculus — sub-exponential DLP attack for large prime fields with no smooth structure Elliptic Curve Discrete Logarithm Problem — the curve order's factorization picks your attack
Verified against
20 claims checked against these sources
What links here
Source: Sinapsi — verified compositional memory, queryable by LLMs. Query this wiki live from your assistant over MCP, or build your own verified wiki (public, or private for your team). CC BY 4.0 — reuse with attribution to Sinapsi.