Shamir's Secret Sharing · on paper

Split a secret into cards.
Any three bring it back.

Your password-manager master key, 2FA recovery codes or wallet seed — turned into printable QR cards for the people you trust. Any K of them recover it. Fewer reveal nothing, not even its length.

Five cards, any three recover — set ····-···

One master password.
Where does it go?

A sticky note

One copy, one thief

Whoever finds it gets everything. Lose it in a move or a fire and it is gone for you too.

Tell one person

One person, one point of failure

They might forget, move away, or be the person who needs protecting against.

heirloom

No single point, either way

Give five people one card each. Any three can act together; one lost card changes nothing; one curious holder learns nothing.

The tool

Never leaves this tab. Up to 512 bytes.

Any 3 of 5 recover · 2 can be lost

Who keeps each card? optional
Advanced

Why fewer cards reveal nothing

Cards you hold:
  1. The secret becomes a curve. Each byte is the height where a random parabola (for “any 3”) crosses the vertical axis.
  2. Each card is one point on it. Card #1 holds the curve's height at x = 1, card #2 at x = 2, and so on.
  3. Three points fix a parabola. With three cards there is exactly one curve — and so exactly one secret.
  4. Two points fit every parabola. With two cards, every possible secret is equally likely. That is not “hard to crack” — there is nothing to crack.

For illustration the curve is drawn over real numbers. heirloom does the same over the finite field GF(28), byte by byte, which makes the “every secret equally likely” statement exact.

Under the hood

GF(28) arithmetic

Shamir over the AES field: carry-less multiplication, inverses by a254, Lagrange interpolation per byte.

A QR encoder from scratch

Segments, Reed–Solomon over GF(28)/0x11D, block interleaving, zig-zag placement and all eight masks — cross-checked against OpenCV.

Typo-proof card text

Crockford Base32 (no I/L/O/U, case-insensitive) in rows with a mod-37 check symbol, so a typo is reported as “row 3”.

Forgery detection

Shares are a Reed–Solomon codeword. With spare cards, a forged or damaged card is outvoted and named.

Length hiding

Type and length are shared along with the secret and padded to 16-byte blocks, so a card does not leak how long the secret is.

Written in Gleam

A pure, typed core compiled to JavaScript — the same code runs this page and the command-line tool.

Prefer a terminal?

The same core ships as a single-file Node.js CLI. Read the secret from stdin, get a printable sheet.

CLI documentation
$ heirloom split -k 3 -n 5 --label "Family vault" < secret.txt
✓ 5 cards written to cards.html · any 3 recover · set PG4F-A60
  self-test passed: the cards recombine to your secret.

$ heirloom combine card1.txt card3.txt card4.txt
tulip-anchor-91-ember
✓ recovered · set PG4F-A60 · cards #1 #3 #4

$ heirloom verify card2.txt
✓ card 1: #2 of 5 · set PG4F-A60 · needs 3

Questions

Is it safe to type a secret into a website?

This page is static files and a strict Content-Security-Policy (connect-src 'none'): the browser itself blocks it from sending anything anywhere. For the cautious: download the offline copy — the whole tool in one HTML file — and open it from disk on a machine without network, or use the CLI on an air-gapped computer.

What if a card is lost or destroyed?

Nothing happens as long as enough cards remain. With 3-of-5, any two can be lost. If you lose more, make a new set — cards from different sets never mix.

What if a holder forges or alters a card?

Every card carries a CRC-32 against accidents. Against deliberate tampering, bring more cards than needed: heirloom cross-checks them and names the card that disagrees.

Do I need this website to recover?

No. The card format is documented in the repository and the math is textbook Shamir; the CLI, the offline copy of this page, or any reimplementation can recover it.

Should I store the cards' HTML file?

No — the file contains every card. Print it, check one card with Recover, then delete the file and clear the print queue.