Why any k work, and k − 1 don't
The secret is the height where a curve crosses the left axis. Each tag is one point on the curve. With k points there's exactly one curve of the right kind through them, so the crossing is pinned down. With one point fewer, a curve fits through every possible crossing.
Drag the ◆ secret up and down the left axis. Tap a tag to tear it off, and tap again to put it back. Drag a tag to forge it: with exactly k tags a forgery goes unnoticed, but with spares the honest tags outvote it. This plot uses ordinary numbers so the curves are easy to see. The real tags use the same algebra over GF(256), bytes 0–255, where a single tag short of k leaves every byte value exactly equally likely.
Split a secret
Type something, choose how many tags and how many it takes to rebuild, and print.
Everything happens in this page: the randomness comes from your browser's crypto.getRandomValues,
and the secret is never sent anywhere.
Re-split makes a fresh, unrelated set: new random curves and a new set ID. Tags from different sets don't mix, and the recover step will say so. Printing sends the tags through your printer queue like any other document.
Recover
Type or paste tag codes, one per line, or scan the QR codes. The page checks each tag's checksum, notices tags from a different split, and rebuilds the secret once it has enough. The camera picture is read by your browser's own barcode detector, on this device.
Try this
- In the explainer, tear tags off until you have one fewer than you need. The fan of curves sweeps the whole axis. Put one back and it collapses to a single curve.
- Still in the explainer, keep exactly k tags and drag one. The curve follows the forgery and the secret moves with it. Now restore all five tags and forge one: the other four outvote it.
- Split something, press try tags from above, then delete one line. "Possible secrets" jumps back to 28 × length: being one tag short is as good as having none.
- Switch to backup mode with a long sentence and any 4 of 6. Each tag's share shrinks to a quarter of the sentence (the 9-byte label and checksum stay). Recover with three of them, and "possible secrets" is far smaller than in secret mode, because backup tags leak.
- Mistype a character, paste a tag twice, or mix in a tag from a re-split. Each one gets caught and named.
- Print the tags, cut them apart, and scan them with your phone's camera app. The QR codes hold the same text as the typed codes.
How it works
One polynomial idea. Any k points pin down exactly one polynomial of degree k − 1: two points fix a line, three a parabola. Put the data into a polynomial, hand out n points on it, and any k of them rebuild it. The page does this once per byte, in GF(256), the same 256-element number system the QR exhibit's error correction uses. There, addition is XOR and every byte value has a partner to divide by, so the curve-fitting from school algebra works exactly, with no rounding.
Two ways to use it. The difference is where the data goes in the polynomial.
| secret mode Shamir, 1979 | backup mode Reed–Solomon erasure code | |
|---|---|---|
| the data is | only the constant term, p(0); the other coefficients are fresh random bytes | all of the coefficients, k bytes per polynomial |
| each tag holds | as many bytes as the secret | about 1/k of the data |
| all n tags together | n× the secret | n/k× the data |
| k − 1 tags reveal | nothing: every secret of that length stays exactly as likely | a lot: each tag removes 8 bits of uncertainty from every k-byte chunk |
| use it for | passwords, recovery codes, keys | long text you're afraid of losing, not of someone reading |
Why does secret mode leak nothing? Fix any k − 1 tags. For each of the 256 possible values of a secret byte, there is exactly one polynomial through those tags and that value, and the random coefficients made each of those polynomials equally likely. So the tags fit every secret equally well. That's the fan of curves in the explainer above, and the page's tests check it exhaustively: for k = 2, 3 and 4, every combination of k − 1 share bytes turns up exactly once for every secret.
What it doesn't protect against
- Someone who finds k tags. That's the deal: k tags are the secret. Put them where no single place, person, or burglary gets k of them. Three tags in the same kitchen drawer are a password on a sticky note with extra steps.
- Learning the length. Every tag records how many bytes the secret is, so one tag says "this password is 28 bytes" and nothing else. Most Shamir tools leak the same thing. If the length matters, pad the secret yourself before splitting.
- A forged tag with no spare. Shamir shares carry no signature. With exactly k tags, a forged one produces a wrong secret, and nothing can tell. With one spare the page notices the tags disagree, and with two or more spares it outvotes the forgery and names it. SLIP-39, below, adds a digest of the secret so a wrong combination is caught even without a spare.
- The moment of splitting. You're trusting this page's code, your browser, and your printer queue while the secret is on screen. Apart from an anonymous visit count when it loads, the page makes no network requests, so you can save it and use it offline. The math above is short enough to check.
- Paper. Thermal receipts fade and inkjet runs when it gets wet. Use a laser printer, and since the QR codes are level Q, they still scan with about a quarter of each code scuffed or torn away.
Where this lives
Hardware wallets. SLIP-39, from SatoshiLabs (the makers of Trezor), splits a wallet's master secret into word lists, one per share, using exactly this math over GF(256). It adds two levels, such as "any 2 of these 3 groups, where the family group needs 2 of 3 and the lawyer group needs 1", plus a checksum on every share and a digest of the secret.
Server secrets. HashiCorp Vault, a widely used secrets manager, starts out "sealed". Its master key is split with Shamir among several operators, by default into 5 shares with a threshold of 3, the same as this page's default. No single person can unlock it, and losing two people doesn't lock everyone out.
Storage. Backup mode is how disks survive losing disks. RAID 6 stores two extra parity blocks per stripe, so any two drives can fail. Backblaze's storage vaults spread every file across 20 machines as 17 data shards plus 3 parity shards, using Reed–Solomon, so any 3 can be lost. It costs 20/17 ≈ 1.18× the space, instead of the 3× of keeping three full copies.
Build plan
- Math core. GF(256) arithmetic (reuse from the main page's QR code), Lagrange interpolation, and share and recover for both modes, byte by byte.
- Round-trip tests for every k-subset of n ≤ 8. In secret mode, check that the k − 1 share distribution doesn't depend on the secret.
- Visual explainer. An interactive plot over the real numbers (for intuition): drag points, watch the unique curve through k of them, and see that k − 1 points fit infinitely many curves through every possible secret.
- Split and print. Text in, n/k chooser, tags out: QR (reuse the encoder, generalized beyond version 3), a base32 text form with a checksum, and a print stylesheet that lays tags out for cutting.
- Recover. Paste or type tag codes, with duplicate and wrong-set detection (tags carry a short set ID). Then camera scanning via
BarcodeDetectorwhere the browser supports it, and typed codes elsewhere. - Write-up. Backup vs secret mode tradeoffs, why this is the basis for key backup in hardware wallets (SLIP-39) and for erasure coding in storage systems, and what it doesn't protect against (a thief who finds k tags).
The deep cut
Adi Shamir's 1979 paper, “How to share a secret,” is two pages long. Its security isn't "hard to break"; it's information-theoretic. With k − 1 shares, every secret is exactly as likely as every other, so there's nothing to compute, even with infinite computing power.
The erasure-code version is why a storage cluster can lose whole drives without losing files. It's also why a Reed–Solomon decoder repairs twice as much damage when it's told which bytes are missing (erasures) as when it has to find them: a known-missing byte costs half as much parity as an unknown wrong one.
Why bother with GF(256) instead of ordinary numbers? Over the integers, Shamir leaks. If the secret is a byte and a share is 1,000 at x = 1 with small random coefficients, that rules out some secrets, because ordinary numbers have sizes and limits. In a finite field there is no "bigger" or "smaller": adding a random byte scrambles a value completely, and division always works. That's what makes "every secret equally likely" exactly true, not just roughly.
Reading
- A. Shamir, “How to share a secret,” Communications of the ACM 22(11), 1979.
- SatoshiLabs, SLIP-0039: Shamir's Secret-Sharing for Mnemonic Codes.
- J. S. Plank, “Erasure codes for storage systems: a brief primer,” ;login:, 2013.
- HashiCorp, “Seal/Unseal,” Vault documentation.
- B. Beach, “Backblaze open-sources Reed–Solomon erasure coding source code,” Backblaze blog, 2015.
- ISO/IEC 18004:2015, QR Code bar code symbology specification (the block tables behind the tags' QR codes).