1. Why 256 bits fit on 64 squares
Bitcoin private keys are integers on the secp256k1 elliptic curve. The valid range is [1, n−1], where n ≈ 2256 − 232 − 977. In practice, almost every 256-bit string is a valid key — the chance of landing in the forbidden zone is about 1 in 2224, which has never happened in the history of Bitcoin and almost certainly never will.
A chessboard has 8 × 8 = 64 squares, but not every square arrangement is a legal chess position. The standard army has exactly 32 pieces (2 kings, 2 queens, 4 rooks, 4 bishops with one of each colour per side, 4 knights, 16 pawns). Counting how many ways these pieces can be placed on 64 squares — with the constraint that pawns sit only on ranks 2 through 7 — yields approximately 2148 distinct positions. One board therefore holds 148 bits; two boards hold roughly 296 bits, which comfortably absorb the 256 bits of a private key.
2. The 32-piece standard-army schema
Instead of inventing new pieces, the visualiser sticks to the standard 32-piece army familiar to every chess player. Every encoded board contains exactly: 1 white king, 1 black king, 1 white queen, 1 black queen, 2 rooks of each colour, 2 bishops of each colour (one on a light square and one on a dark square), 2 knights of each colour, and 8 pawns of each colour. The full constraint list is:
These three constraints define the precise set of positions over which the bijection is built. The numerical placement order used by the algorithm is fixed (kings, queens, rooks, bishops, knights, pawns) so that encoder and decoder agree on the digit weights.
3. Anatomy of a Bitcoin private key
A raw private key is just 32 random bytes. To make it easy to transport between wallets, Bitcoin defines the WIF (Wallet Import Format):
Mainnet vs testnet — a common confusion. The 32-byte private key itself is just a number; it is identical on every Bitcoin network. The only difference is the visible encoding: WIF uses prefix 0x80 on mainnet and 0xEF on testnet, addresses use bc1… / 1… vs tb1… / m… / n…. The chessboard encodes the key, not the network — so the same two positions produce both addresses, depending only on how you choose to print them. Our converter shows mainnet outputs because that is what people recognise.
For our purposes, only the middle 32 bytes matter — that is what we paint onto the board. The prefix, flag and checksum are added automatically when displaying the WIF.
4. From key to address: ECDSA → HASH160
Given the private key k, the corresponding public key is the elliptic-curve point P = k · G, where G is the fixed generator point of secp256k1. This step is one-way: recovering k from P is the discrete-log problem, which is computationally infeasible.
Then the address is computed as:
5. Checksums: Base58Check vs Bech32
Base58Check (used by legacy addresses and WIF keys) appends a 4-byte truncated double-SHA-256 to the payload, then encodes the whole thing in a 58-character alphabet (no 0, O, I, l to reduce confusion). Any single typo has roughly a 1 in 232 chance of producing a "valid" string — practically zero.
Bech32 (BIP-173, used by SegWit) is much smarter: it uses a 30-bit BCH polynomial code over GF(32). It detects any single-symbol error with probability 1, and any pair of symbol errors with probability ≥ 1 − 2−30. Bech32 also uses a 32-symbol alphabet that maps perfectly to the 32 light squares on a chess board — a curious coincidence we exploit in the address-board section below.
6. The bijection in code
Each board represents a 128-bit half of the key (low half on board 1, high half on board 2). Because the schema only admits a fixed set of legal positions, the bijection cannot be a simple per-square lookup — it is a combinatorial unranking. Place pieces in a fixed order (kings, queens, rooks, bishops, knights, pawns); for each step, choose k squares out of the remaining n empty squares; the choice index acts as a digit in a mixed-radix system whose base at each step is C(n, k) for that step.
Bishops are handled with a slightly different step: each side picks one light-square bishop out of the available light squares and one dark-square bishop out of the available dark squares, so the base at that step is nL × nD. Pawns are restricted to ranks 2\u20137 by filtering the remaining empty squares before the binomial choice. The full algorithm is implemented in roughly 40 lines of pure JavaScript using BigInt; you can read it directly in the page source of the converter.
7. The visualiser: two boards, editable FENs
The converter on this site renders both halves as real chess diagrams using chessboard.js with the Wikipedia piece set \u2014 the same library and graphics used by the league's Vote Chess room. The board on the left holds the low 128 bits of the key, the one on the right holds the high 128 bits. A copy of the position in FEN notation appears below each board in an editable input.
You can paste any FEN you like. The board re-renders immediately so you can always see the position, and the input border turns green or red depending on whether the position fits the bijection schema:
A small copy-to-clipboard button beside each FEN input copies the position string for sharing or storage. The "Famous positions" picker, the random-board button and the PNG / share buttons all go through the same render pipeline, so anything that appears on a board can be exported back as FEN at any time.
8. Applications
- Chess paper wallet. Print the position, slip it inside a chess opening book on your shelf. Plausible deniability + zero electronics + human-readable.
- Generative art. Mint chessboards as NFTs that are also valid Bitcoin keys. Each piece-arrangement is provably unique.
- Vanity boards. Brute-force boards that decode to addresses starting with chosen letters (bc1q… → "bc1qchess…").
- Education. A chessboard is the most viscerally satisfying way to teach the size of cryptographic key spaces.
- Memorisation. Chess players memorise hundreds of positions effortlessly. A board is vastly easier to remember than a 52-character WIF string.
Be the first to comment!