Note

Baby Step Giant Step

Baby Step Giant Step Algorithm.

By Roman Akhtariev

Baby-Step Giant-Step (BSGS)

The core idea is beautifully simple once you see it — it's essentially a meet-in-the-middle strategy applied to the discrete logarithm problem.

The Problem

You want to find xx such that gx=h(modp)g^x = h \pmod{p}. Naively, you'd try x=0,1,2,,p1x = 0, 1, 2, \dots, p-1 which takes O(p)O(p) time where pp is the group order.

The Key Insight

Write x=im+jx = i \cdot m + j where m=pm = \lceil\sqrt{p}\rceil and 0i,j<m0 \le i, j < m. Then:

gim+j=hg^{im + j} = h

gj=h(gm)ig^j = h \cdot (g^{-m})^i

You've split one search over pp values into two searches over p\sqrt{p} values each.

The Two Phases

Baby steps — Precompute and store gjg^j for j=0,1,,m1j = 0, 1, \dots, m-1 in a hash table. These are small, incremental steps through the group.

Giant steps — Compute h(gm)ih \cdot (g^{-m})^i for i=0,1,2,i = 0, 1, 2, \dots and check if it's in your table. Each iteration jumps by mm positions — hence "giant" steps.

When you find a collision, you've got gj=hgimg^j = h \cdot g^{-im}, so h=gim+jh = g^{im+j} and x=im+jx = im + j.

Walkthrough: 5x20(mod53)5^x \equiv 20 \pmod{53}

Here g=5g = 5, h=20h = 20, and the group order is p=52p = 52 (since (Z/53Z)(\mathbb{Z}/53\mathbb{Z})^* has order 531=5253 - 1 = 52).

Setup. Compute m=52=8m = \lceil\sqrt{52}\rceil = 8.

Baby steps — build a table of gjmod53g^j \bmod 53 for j=0,,7j = 0, \dots, 7:

jj5jmod535^j \bmod 53
01
15
225
319
442
551
643
73

Store as a lookup: {10,  51,  252,  193,  424,  515,  436,  37}\{1 \mapsto 0,\; 5 \mapsto 1,\; 25 \mapsto 2,\; 19 \mapsto 3,\; 42 \mapsto 4,\; 51 \mapsto 5,\; 43 \mapsto 6,\; 3 \mapsto 7\}.

Giant steps — we need gm=58mod53g^{-m} = 5^{-8} \bmod 53. Since 5815(mod53)5^8 \equiv 15 \pmod{53}, we find 15146(mod53)15^{-1} \equiv 46 \pmod{53} (verify: 1546=690=1353+115 \cdot 46 = 690 = 13 \cdot 53 + 1). Now compute h(gm)i=2046imod53h \cdot (g^{-m})^i = 20 \cdot 46^i \bmod 53:

ii2046imod5320 \cdot 46^i \bmod 53In table?
020No
119Yes! j=3j = 3

Result. x=im+j=18+3=11x = i \cdot m + j = 1 \cdot 8 + 3 = 11.

Verify: 511=5853=1519=285=553+2020(mod53)5^{11} = 5^8 \cdot 5^3 = 15 \cdot 19 = 285 = 5 \cdot 53 + 20 \equiv 20 \pmod{53}. Correct.

We checked just 8+1=98 + 1 = 9 values instead of scanning all 52. With larger groups, this savings becomes dramatic.

Why It Works Mathematically

Every integer x[0,p)x \in [0, p) can be uniquely decomposed as x=im+jx = im + j with 0j<m0 \le j < m and 0i<m0 \le i < m. So the baby steps cover all possible "remainders mod mm" and the giant steps cover all possible "quotients by mm." The two sets are guaranteed to collide at the right answer.

Complexity

  • Time: O(p)O(\sqrt{p}) — at most p\sqrt{p} baby steps + p\sqrt{p} giant steps
  • Space: O(p)O(\sqrt{p}) — storing the baby-step table

This is optimal for generic group algorithms (by Shoup's lower bound), meaning you can't do better without exploiting special group structure.