
How RC2's π table was made
The 256 numbers in the key schedule of Ron Rivest’s RC2 cipher were said to come from π, but the method was never published. A card shuffle that uses π’s digits as dice reproduces both of RC2’s tables exactly.
以下正文同步自 Hacker News,版权归原站所有,已转换为易读排版。
The 256 numbers in the key schedule of Ron Rivest’s RC2 cipher were said to come from π, but the method was never published. A card shuffle that uses π’s digits as dice reproduces both of RC2’s tables exactly.
RFC 2268 says the 256-byte table PITABLE in RC2’s key schedule is “based on the digits of PI”, but gives no method, and a second table in the same document is given no origin at all. Both are reproduced exactly by the Fisher–Yates shuffle, using the decimal digits of π as its source of randomness: each draw reads exactly three digits, and draws that would bias the result are discarded. PITABLE starts at the leading 3; the second table starts four digits later. Rivest’s MD2 hash uses the same shuffle but reads a varying number of digits per draw, which may be why the connection went unnoticed. This is very likely how the tables were originally made, though how Rivest arrived at the rule is not documented. The question was raised in public by an engineer at RSA Data Security in 1996; an extensive search found no earlier public answer. The result has no bearing on RC2’s security.
RC2 is a block cipher Ron Rivest designed in the late 1980s. To turn a key into the longer internal key it actually encrypts with, it passes every byte through a fixed table: the numbers 0 to 255 in a scrambled order. Every implementation of RC2 carries the same 256 numbers.
A table like this is where a designer could, in principle, hide a weakness. Cryptographers guard against that suspicion by deriving such tables from a public constant like π and showing the derivation, so anyone can rebuild the table and confirm nothing was chosen by hand. These are known as “nothing-up-my-sleeve” numbers, and they only reassure if the derivation is public.
RC2 named its constant but never its derivation. Rivest’s specification, RFC 2268, calls the table “an array of ‘random’ bytes based on the digits of PI” and prints it without a method.1 When the cipher’s code leaked in 1996, an engineer at RSA Data Security, which owned RC2, listed in public as an open question how one could tell whether the table came from π.2 No answer followed, and some implementations, such as LibTomCrypt, still carry the comment from the leaked code: “probably derived somehow from pi”.3,4 Section 5 tells that history. This note gives a construction that reproduces the table exactly.
Picture 256 cards numbered 0 to 255, laid out in order. Take each card in turn, from the second to the last, and swap it with a randomly chosen card at or before its own position. This is the Fisher–Yates shuffle, the standard way to shuffle fairly, and it was not secret. What was never published is where the randomness came from. The tables are reproduced exactly when the dice are the decimal digits of π, read exactly three digits for every draw, starting from the first 3. Figure 1 plays the first steps.
The first eight of 256 positions, shown in decimal. All 256 match.
This animation requires JavaScript. The first steps are: read 314, so card 1 swaps with place 314 mod 2 = 0; read 159, so card 2 swaps with place 159 mod 3 = 0; read 265, so card 3 swaps with place 265 mod 4 = 1; and so on.
Written out precisely, the construction is Algorithm 1. The discard step keeps the draws fair. When the number of available places does not divide 1,000 evenly, a draw that lands in the few highest values (960 to 999 when there are 240 places, for example) is discarded and three new digits are read. Over the whole shuffle this happens 21 times, two of them at the run of six 9s at the 762nd decimal place of π known as the Feynman point.a In total the shuffle uses 828 digits.
input: d = 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, … (decimal digits of π)
rand(n): loop x ← next three digits of d // 0…999 if x < n · ⌊1000 / n⌋: return x mod n // otherwise discard x
S ← [0, 1, …, 255] for i ← 2 to 256: j ← rand(i) swap S[j], S[i − 1] return S // = PITABLE
Why it may have stayed hidden. In 2014 Rivest confirmed that his MD2 hash builds its π table with the same shuffle.5 But MD2 reads as few digits as each draw needs: one digit while there are up to 10 places to choose from, two up to 100, three beyond that. Applied to RC2, MD2’s exact rule matches 1 of 256 entries, no better than chance, so the obvious test would have suggested the tables were unrelated. The only change needed is to read three digits every time.
3Verification
Algorithm 1 reproduces RFC 2268’s PITABLE in all 256 positions. Figure 2 runs it in your browser, alongside five plausible alternatives, and compares every output with the published table.
This figure requires JavaScript. The reproduction script performs the same comparison and the controls in Table 1.
The match is not the kind of coincidence a broad search could stumble on. There are about 10507 possible orderings of 256 numbers. The search that found the rule tried roughly 100,000 candidates (four digit sources, seven ways of drawing a number, six shuffle orders, 300 starting points, and both the table and its inverse), and exactly one matched in full: the simplest. Variants that change the digit source or the width of each draw fall to chance level. Dropping the discard step leaves the first 112 draws unchanged, so 29 early positions still match before it drifts (Table 1).
The hexadecimal method in Table 1 is included because, when asked “how was the RC2 PITABLE generated from the digits of pi” on 17 October 2026, Google’s AI Overview described it. Its own worked example begins 24 3f 6a; the published table begins d9 78 f9.
The result was reproduced twice after it was found: by a second implementation written from the RFC and a one-paragraph description of the rule, without access to the first, and by a third using its own computation of π and a fresh copy of the RFC.
Section 6 of RFC 2268 prints a second permutation of 0 to 255, the RFC’s Table[], called the version table here. It encodes an effective key length of 1 to 255 bits as the RC2Version parameter of RC2-CBC, as used in PKCS #5 and related standards,6 and the RFC says only that it “is not the same table that appears in the key expansion phase”.1 It is Algorithm 1 started at the fifth digit of π (5926…) instead of the first. It matches in all 256 positions, again using 828 digits with 21 discarded draws. Both tables in the RFC can therefore be produced by one generator, run from two starting points.
In the 1980s the United States controlled the export of strong encryption much as it controlled weapons, and the National Security Agency carried out the technical review. Lotus Development was preparing to sell Notes, a business application with encryption built in, developed for it by Ray Ozzie’s company Iris Associates, and could not obtain an export licence for it using the standard cipher, DES. According to Steven Levy’s account, the NSA agreed in mid-1987 to evaluate a replacement. Lotus engaged Rivest, who designed RC2 within a few weeks; Lotus paid for the work and RSA Data Security held the rights.7 (Rivest’s 1997 draft specification is dated “Created 1987”; a 1998 paper he co-authored gives the design date as 1989.1,8)
Rivest submitted the design to the NSA, which asked for “a couple of tweaks”. Ozzie, who led the negotiations, put the obvious question to Rivest:
Rivest judged the suggestions technically sound and adopted them. Levy’s account does not say what they were.
In 1989 the NSA verbally offered Lotus an export licence for RC2 with keys limited to 32 bits. In 1992 an agreement negotiated through the Software Publishers Association gave expedited export approval to retail software using RC2 or its sibling RC4 with keys of at most 40 bits,9 on the condition that RSA and its licensees keep the designs secret.7 RC2 shipped worldwide inside commercial products while its internals, including the table, remained unpublished.
On 29 January 1996, RC2’s source code was posted anonymously to the Usenet group sci.crypt; references to debugging tools suggested it had been reverse-engineered. Four days later Robert Baldwin of RSA Data Security posted a list of open technical questions about the cipher to the cypherpunks mailing list. The first concerned the table:
No answer appears in the thread. In March 1998 Rivest published RC2 as RFC 2268, printing the table in full without a construction.1 A paper he co-authored the same year states only that the table “was derived from the expansion of π”.8
Rivest’s MD2 hash function contains its own 256-byte permutation, “constructed from the digits of pi” according to its specification,10 and it too was unexplained for years. In 2013, commenters on Hacker News and Cryptography Stack Exchange noted that both the MD2 and RC2 tables remained unexplained.11 In 2014 a Stack Exchange user obtained the MD2 construction from Rivest by email and posted it.5 We found no published work that applies it to RC2.
It helps to separate three claims. Established by computation: Algorithm 1 reproduces both published tables exactly, and anyone can check this with the published script. Strongly supported, but not proven: this is the method, or something very close to it, by which the tables were originally made. A short rule that matches every entry of both tables, while its near variants fail, is hard to explain any other way, and the rule is Rivest’s own documented MD2 shuffle with one change. Not established: exactly how Rivest arrived at it, including whether he tried other rules or starting points before settling on this one. The tables alone cannot tell us that.
The last point matters for the “nothing up my sleeve” question. The 256 entries were not chosen one by one: they follow from a short rule applied to π. That leaves far less room for deliberate selection than a table chosen entry by entry, but it does not remove it entirely. A designer could, in principle, have tried several simple rules or starting points and kept one; the second table’s different starting point shows that such choices were made. Nothing here tells us what the NSA’s 1987 changes were, or whether they touched this table.
The result does not affect RC2’s security. The cipher has long been deprecated, though it persists in older PKCS #12 certificate files, and knowing the origin of a public table makes it neither weaker nor stronger. Rivest presumably always knew the method; the claim here is only that it had not been published.
The search for earlier work covered the 1996 cypherpunks archive and part of the sci.crypt discussion (Google Groups’ search was rate-limited), the 1998 design paper, the Japanese government’s CRYPTREC evaluation of RC2, Cryptography Stack Exchange, Hacker News, GitHub, X, IACR ePrint, and searches in Chinese, Russian and Japanese. It found the question asked several times and never answered. Semantic Scholar and print-only sources could not be searched fully, so an earlier explanation may exist in a source we did not reach. Corrections are welcome and will be credited here.
This result came from an experiment in using AI agents on neglected problems whose answers can be checked exactly. In October 2026, Anthropic reported that its model Claude had traced the seeds of the NIST elliptic curves to a standard C library random-number generator seeded with timestamps from 1997 and 1998.12,13 I set up a pipeline that collects long-unanswered questions, ranks them by whether a solution would verify itself, and assigns the most promising to AI coding agents.
RC2’s table was the first result. The agent, Claude, reasoned that if one of Rivest’s π tables had been explained, the other might yield to the same method, and found the three-digit rule. OpenAI’s Codex wrote the independent second implementation described in Section 3, and a later sweep of other “derived from π” tables found the second RC2 table. None of this needs to be taken on trust: the script in the repository computes π and checks both tables against the RFC in under a second.
C
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。