Research note · Cryptography history

How was RC2’s pi table made?

It’s a card shuffle, with the digits of pi as the dice. Both of the cipher’s 256-byte tables rebuild exactly that way, thirty years after RSA’s own engineer asked how.

By Khalid HamadehOctober 17, 20267 min read
The short version

RFC 2268 says RC2’s PITABLE is “based on the digits of PI” and never says how. It is the shuffle Ron Rivest used for MD2’s table, with one change: every draw reads exactly three decimal digits. Run that from the leading 3 and you get PITABLE, 256 of 256 bytes. Run it four digits later and you get the RFC’s second, unexplained table. A short script with no dependencies reproduces both in under a second.

256 / 256
bytes rebuilt, in each of the two tables
828
digits of pi each table consumes
1996
when RSA’s own engineer asked the question in public
1 of ~100k
candidate rules tested that fits all 256 bytes
See it

Rebuild the table in your browser

This page computes pi itself, runs the shuffle, and checks every byte against the table printed in RFC 2268. Switch to one of the wrong methods to see what a near miss looks like. It’s about one byte in 256, which is chance.

PITABLE, RFC 2268 §2
matching … / 256

Each cell is one byte the shuffle produced. Lit cells equal the RFC’s byte at that position.

The interactive rebuild needs JavaScript. The Python script does the same check.

The rule

A shuffle, with pi as the dice

Start with the numbers 0 to 255 in order. Walk up the list. At each step, pick a random position among the ones already visited and swap it with the newest one. That is the Fisher–Yates shuffle (Durstenfeld’s version), the standard way to shuffle a deck fairly. Rivest’s only twist is where the randomness comes from: the decimal digits of pi, read three at a time.

# digits of pi, leading 3 included:
# 3 1 4 1 5 9 2 6 5 3 5 8 9 7 9 …

rand(n):
    x = next three digits      # 0 … 999
    if x < n × floor(1000 / n):
        return x mod n
    else: throw x away, read again

S = [0, 1, …, 255]
for i = 2 … 256:
    j = rand(i)
    swap S[j] and S[i−1]

# PITABLE = S
# 828 digits read, 21 draws thrown away

The throw-away step is what makes the dice fair. With n = 3, the thousand values 000 to 999 don’t split evenly into three groups, so the rule discards 999 and draws again. Over the whole shuffle that happens 21 times. Leave the step out and the shuffle drifts off course at the first discarded draw, ending at 29 of 256 bytes.

Where the idea came from

MD2’s shuffle, with one change

Rivest’s MD2 hash (RFC 1319) has its own 256-byte “pi” table, and for 25 years nobody had explained that one either. In 2014 a user on Cryptography Stack Exchange emailed Rivest and posted his reply: the same shuffle, driven by pi’s digits. MD2’s version reads as few digits as it needs: one digit while n ≤ 10, two while n ≤ 100, three after that.

RC2 uses the identical loop and the identical rejection rule, but always reads three digits. That small difference is enough to hide the link. Apply MD2’s exact rule to RC2 and you get 1 matching byte out of 256, so anyone who tried the obvious thing in 2014 would have concluded the tables were unrelated. Rivest’s own description dates RC2 to 1987, and a 1998 paper he co-wrote says 1989, the year MD2 was designed. Either way the two tables come from the same years and the same hand.

The other table

RC2’s second table is the same generator, four digits later

RFC 2268 has a second permutation in section 6. It turns a key length into the RC2Version number stored in RC2-CBC parameters, and the RFC says only that it is “not the same table that appears in the key expansion.” It gives no origin. Start the same shuffle at the fifth digit of pi (5926…) instead of the first, and it rebuilds byte for byte: 256 of 256, again 828 digits with 21 draws thrown away. That’s presumably how Rivest made a second table that was different from the first and just as traceable, by running his generator again from a different place.

Checking it

Why this isn’t a coincidence

There are about 10507 ways to order 256 bytes. The search that found this rule tried roughly 100,000 candidates: four digit sources, seven ways of drawing a number, six shuffle orders, 300 starting points. Exactly one matched all 256 bytes, and it was the simplest of them. Every plausible neighbour lands at chance.

The rule abovedecimal pi, 3 digits per draw, from the leading 3
256
Same, without the throw-away step
29
Pi’s hex digits, keeping first appearancesthe method Google’s AI Overview describes
2
MD2’s exact digit rule
1
Starting one digit later
1
Digits of e instead of pi
0
Bytes of RFC 2268’s PITABLE matched by each method, out of 256. A random permutation matches about 1 on average. Every number here is reproduced by the script and by the rebuild above.
If you search for this today, Google’s AI Overview describes a different method: pi’s hexadecimal digits taken in pairs, skipping repeats. That method matches 2 of 256 bytes. Its own worked example starts 24 3f 6a; the real table starts d9 78 f9.
The record

Thirty years of “derived somehow from pi”

1987–1989

Rivest designs RC2 for RSA Data Security as a trade secret. His later write-up says “Created 1987”; the 1998 paper says 1989.

Jan 1996

RC2’s source code is posted anonymously to sci.crypt. The table carries a comment that implementations still ship today:

“256-entry permutation table, probably derived somehow from pi”
2 Feb 1996

Robert Baldwin of RSA Data Security posts a list of open technical questions about RC2 to the cypherpunks list. The first one:

“How can you tell whether the permutation is based on some sequence of digits from PI?”

Nobody in the thread answers it.

1998

Rivest publishes RFC 2268. The table is “based on the digits of PI”; the method isn’t given. A paper he co-wrote that year says only “derived from the expansion of π.”

2013

On Hacker News and Cryptography Stack Exchange, people note that the MD2 table “(and rc2 apparently)” remain unexplained.

2014

Rivest explains MD2’s table by email. No public record shows anyone applying that method to RC2.

Oct 2026

Both RC2 tables rebuilt from pi. That’s this note.

What it does and doesn’t mean

A small mystery, closed

It changes nobody’s security. RC2 has been deprecated for years, though it survives in old PKCS #12 certificate files, and the origin of a fixed public table doesn’t make it weaker or stronger. What it settles is the “nothing up my sleeve” question. Designers derive constants from pi so outsiders can trust they weren’t chosen to plant a weakness. Until now, RC2’s table only said it came from pi. Now it demonstrably does.

Rivest always knew. My claim is only that the method hadn’t been published. The search for prior work covered the 1996 mailing-list archives, the 1998 design paper, a Japanese government evaluation of RC2, Cryptography Stack Exchange, Hacker News, GitHub code search, X, and searches in Chinese, Russian and Japanese. It found people asking, and nobody answering. If you know of an earlier derivation, tell me and I’ll credit it here.

How I found it

Hunting for puzzles that check themselves

This came out of an experiment. In October 2026 Anthropic traced the seeds of the NIST elliptic curves to an old random-number function and some 1990s timestamps. It made me wonder how many small, neglected puzzles have an answer that would prove itself if anyone looked. I set up a pipeline to find them. It harvests thousands of old unanswered questions, scores them for whether a solution could be checked exactly, and sends AI coding agents after the best ones.

RC2 was the first hit. The agent, Anthropic’s Claude, reasoned that if one of Rivest’s pi tables had been explained, his other one should yield to the same method. It found the three-digit rule in about fifteen minutes. A second model, OpenAI’s Codex, then rebuilt the result from the RFC and a one-paragraph description without seeing our code. A third rebuild, written separately again, used its own pi routine and a fresh download of the RFC. All three agree. A later sweep across other “derived from pi” tables found the second RC2 table.

None of that needs to be taken on trust. The script is on GitHub: no dependencies, it computes pi itself, and it prints True twice.

Sources. Tables: RFC 2268 §2 and §6. Dates: draft-rivest-rc2desc-00 (“Created 1987”) and Knudsen, Rijmen, Rivest and Robshaw, On the Design and Security of RC2, FSE 1998 (“designed in 1989”). The 1996 comment: the leaked rc2.c as archived in the funet crypto collection. Baldwin’s question: cypherpunks archive, message 48998, 2 Feb 1996. MD2’s method: Cryptography Stack Exchange question 11935, answer of 2 Aug 2014. Match counts: computed by the published script; the search that ruled out about 100,000 alternatives is logged in my working files and available on request.

  1. RFC 2268: A Description of the RC2(r) Encryption Algorithm (Rivest, 1998)
  2. draft-rivest-rc2desc-00 (1997)
  3. On the Design and Security of RC2 (FSE 1998)
  4. RFC 1319: The MD2 Message-Digest Algorithm
  5. How is the MD2 hash function S-table constructed from Pi? (Cryptography Stack Exchange)
  6. “RC2 technical questions”, R. Baldwin, cypherpunks, 2 Feb 1996
  7. Hacker News comment, 24 Dec 2013
  8. khalid-hamadeh/rc2-pi-tables (the reproduction script)
Quick answers

Common questions

How was RC2's PITABLE generated?
PITABLE is a shuffle of the numbers 0 to 255 driven by the decimal digits of pi, starting at the leading 3. For i = 2 to 256, read the next three digits as a number x; if x is below n times floor(1000/n) with n = i, take j = x mod n, otherwise discard x and read three more; then swap positions j and i-1. It uses 828 digits, rejects 21 draws, and matches the table in RFC 2268 byte-for-byte. It is the shuffle Rivest described for MD2, except that every draw reads exactly three digits.
Is RC2's PITABLE made from the hexadecimal digits of pi?
No. It comes from the decimal digits. Taking pi's hexadecimal digits in pairs and keeping each byte the first time it appears, a method some AI-generated answers describe, matches only 2 of the 256 bytes, which is chance. The real table starts d9 78 f9; the hexadecimal digits of pi start 24 3f 6a.
Where does RC2's version table in RFC 2268 come from?
RFC 2268 section 6 prints a second 256-byte permutation that turns effective key bits into an RC2Version number for RC2-CBC parameters, and gives no origin for it. It comes from the same generator as PITABLE, started four digits of pi later (at 5926…). It also uses 828 digits with 21 rejected draws, and it matches 256 of 256 bytes.
Does this change RC2's security?
No. RC2 is long deprecated, and knowing where a fixed public table came from does not weaken or strengthen it. What it settles is the 'nothing up my sleeve' question: the table is what Rivest said it was, a permutation derived from the digits of pi, with no hidden structure chosen by hand.
Check it yourself

A short Python script, no dependencies

The script computes pi, rebuilds both tables, compares them with RFC 2268, and runs the controls. If you find an earlier derivation, or a hole in this one, I’d like to hear about it.

Get the script → Get in touch

First published October 17, 2026. RC2 tables as printed in RFC 2268; every match count is reproduced by the published script.