Python 3 and a terminal are all you need — no libraries, no accounts, no
coins. macOS and Linux ship with Python; on Windows install it from
python.org with “Add python.exe to PATH” ticked. Check with
python3 --version, which should print something like
Python 3.12.3.
Use the practice phrase printed below, never your own. It comes from the BIP-39 standard’s published test cases, so your output will match this page exactly. Everything you build here — the fingerprint, the split, the restore drill — works identically on a real phrase, but a real phrase belongs on paper or metal, not in a file on a computer.
Why Backups Matter More in Crypto
In traditional finance, if you lose access to your bank account, you can prove your identity and recover access. In cryptocurrency, there is no recovery mechanism. If you lose your private keys or seed phrase and have no backup, your funds are gone permanently. It is estimated that 3-4 million Bitcoin (worth hundreds of billions of dollars) are permanently inaccessible due to lost keys.
The 3-2-1 Backup Rule Applied to Crypto
The classic 3-2-1 backup strategy from data management applies well to seed phrase storage:
- 3 copies of your seed phrase
- 2 different storage mediums (e.g., paper + metal)
- 1 copy in a different physical location (e.g., bank safety deposit box or trusted family member's safe)
This protects against house fires, floods, theft, and localized disasters that could destroy a single backup.
Physical Storage Options
What NOT to Do
Every digital copy is a potential attack vector. Cloud services get breached, devices get malware, and photos get synced to servers you do not control.
- Cloud photos/screenshots — automatically synced to Google, Apple, or Dropbox servers
- Email drafts — accessible to anyone who compromises your email account
- Note-taking apps — Evernote, Notion, Google Keep all sync to the cloud
- Password managers — although encrypted, a single master password compromise exposes everything
- Plain text files on your computer — trivially accessible to any malware
- Unencrypted USB drives — easily lost, stolen, or degraded over time
Geographic Distribution
Storing all copies in the same building defeats the purpose of multiple backups. Consider:
- Copy 1: Metal backup in your home safe
- Copy 2: Paper backup in a bank safety deposit box
- Copy 3: Metal backup at a trusted family member's home (in a sealed, tamper-evident envelope)
Some advanced users split their seed phrase across multiple locations (e.g., words 1-8 in location A, words 9-16 in location B, words 17-24 in location C). This adds complexity and risk — if any single location is lost, you lose everything. Multi-signature wallets are a better solution for distributed security.
Multi-Signature Wallets
For high-value holdings, a multi-signature (multisig) wallet requires multiple independent keys to authorize a transaction (e.g., 2-of-3 or 3-of-5). This means:
- No single key compromise can steal your funds
- You can lose one key and still access your cryptocurrency with the remaining keys
- Keys can be distributed across different devices, locations, or trusted individuals
Multisig adds complexity to setup and transactions, but it eliminates the single point of failure that a single seed phrase represents.
Inheritance Planning
If something happens to you, can your family access your cryptocurrency? Without planning, the answer is almost certainly no.
- Document the existence of your crypto holdings (without revealing seed phrases) in a secure location your family can access
- Provide instructions for recovery that a technically capable person can follow
- Consider a sealed envelope with a trusted attorney or family member
- Some users employ time-locked smart contracts or dead man's switch services, though these add their own risks
Now Test a Backup Properly, in Five Steps
Most backups are never tested, and an untested backup is a guess. In the next twenty minutes you will build the two tools that turn a guess into a fact: a short fingerprint that lets you check a written copy without ever exposing it, and a mathematical split that lets you store a secret in three places while no single place holds it. Then you will damage a copy on purpose and confirm your own checks catch it. Every number below came from running these files.
Go: open a terminal in a folder you can write to, such as
cd ~/Desktop (Windows: cd %USERPROFILE%\Desktop).
Do: save this as fingerprint.py and run
python3 fingerprint.py. It reduces a recovery phrase to eight characters
through the same computation wallets use, then compares a correct phrase with one where the
last word was misread.
import hashlib, unicodedata
def fingerprint(phrase):
seed = hashlib.pbkdf2_hmac("sha512",
unicodedata.normalize("NFKD", phrase).encode(),
b"mnemonic", 2048)
return hashlib.sha256(seed).hexdigest()[:8].upper()
original = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
copied = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abort"
print("phrase on the metal plate :", fingerprint(original))
print("phrase read back from it :", fingerprint(copied))
print("backup is trustworthy :", fingerprint(original) == fingerprint(copied))
You should see: two eight-character codes that do not match, and a verdict:
phrase on the metal plate : 62A772F8
phrase read back from it : 0DC31040
backup is trustworthy : False
about and abort differ by one letter and are neighbours in the word list — the classic misreading of your own stamped metal. A fingerprint turns that invisible error into a visible mismatch. It is also safe to keep: it cannot be reversed into the phrase, so you can store it in a password manager, in a note on your phone, or written on the outside of the envelope.
If not: if both codes are identical, the two phrase lines are the same
— check the final word of copied really says abort. If Python
reports TypeError: pbkdf2_hmac() argument 'salt' must be bytes, the
b in front of "mnemonic" is missing.
Go: same folder.
Do: save this as shamir.py. It prints nothing on its own; it
is the tool the next three steps use. The idea is a hundred years old and beautifully simple:
draw a straight line whose height at zero is your secret, and hand out points on that line.
Any two points define the line. One point defines nothing.
import secrets
P = 2**521 - 1 # a prime larger than any 256-bit secret
def split(secret_int, shares=3):
"""2-of-N: a straight line through the secret, sampled at x = 1, 2, 3..."""
slope = secrets.randbelow(P)
return [(x, (secret_int + slope * x) % P) for x in range(1, shares + 1)]
def combine(two_shares):
"""Two points define the line; its value at x = 0 is the secret."""
(x1, y1), (x2, y2) = two_shares
slope = (y2 - y1) * pow(x2 - x1, -1, P) % P
return (y1 - slope * x1) % P
You should see: nothing. python3 shamir.py should return to
the prompt in silence — that means the file parses and the functions are ready.
If not: TypeError: pow() 2nd argument cannot be negative
means you are on Python 3.7 or older, where pow(x, -1, P) is not supported
— check python3 --version and upgrade, or replace that call with
pow(x2 - x1, P - 2, P), which computes the same inverse.
Go: same folder, next to shamir.py.
Do: save this as split3.py and run it. Picture the three
shares going to a home safe, a bank box and a trusted relative.
import hashlib
from shamir import split, combine
secret = int.from_bytes(hashlib.sha256(b"my recovery phrase").digest(), "big")
parts = split(secret)
for x, y in parts:
print(f"share {x} (give to a different place): {y % 10**20:020d}...")
print()
print("shares 1+2 rebuild it :", combine([parts[0], parts[1]]) == secret)
print("shares 1+3 rebuild it :", combine([parts[0], parts[2]]) == secret)
print("shares 2+3 rebuild it :", combine([parts[1], parts[2]]) == secret)
You should see: three long share numbers — yours will differ, because the line is drawn at random each time — and then three confirmations that every pair works:
share 1 (give to a different place): 32487806227639429514...
share 2 (give to a different place): 79727811151475398284...
share 3 (give to a different place): 26967816075311367054...
shares 1+2 rebuild it : True
shares 1+3 rebuild it : True
shares 2+3 rebuild it : True
Read what that buys you. A burglar who finds one share gets nothing. A house fire that destroys one share costs you nothing. Compare that with the usual advice to keep three copies of the whole phrase, where every copy is a complete loss if found.
If not: if any line says False, the arithmetic in
combine lost a % P — compare it against step 2.
ModuleNotFoundError: No module named 'shamir' means the two files are not in the
same folder.
Go: same folder. Claims about security are worth checking, including this page’s.
Do: save this as onlyone.py and run it. It takes the
position of an attacker holding exactly one share, and asks whether that share rules any
secret out.
from shamir import P
y1 = 987654321987654321 # pretend this is the only share you hold
for guess in [0, 42, 2**255, P - 1]:
slope = (y1 - guess) % P # a slope that fits ALWAYS exists
fits = (guess + slope) % P == y1
print(f"secret could be 2^{guess.bit_length():<3} -> a matching slope exists: {fits}")
print("one share fits every possible secret, so it reveals none of them")
You should see: every candidate surviving, from the smallest possible secret to the largest:
secret could be 2^0 -> a matching slope exists: True
secret could be 2^6 -> a matching slope exists: True
secret could be 2^256 -> a matching slope exists: True
secret could be 2^521 -> a matching slope exists: True
one share fits every possible secret, so it reveals none of them
This is a stronger guarantee than encryption gives you. There is no key to crack and no computer fast enough to help, because the missing information does not exist in the share — a single point is consistent with every line you could draw through it.
If not: a False anywhere means the % P was
dropped from the slope line. If you get ValueError: Invalid format
specifier, the :<3 inside the f-string was mistyped — it is a
colon, a less-than sign, then a three.
Go: same folder. This is the drill that makes the whole system real.
Do: save this as drill.py and run it. It changes one digit of
share 2, exactly as a hand-copying error would, and then rebuilds.
import hashlib
from shamir import split, combine
secret = int.from_bytes(hashlib.sha256(b"my recovery phrase").digest(), "big")
parts = split(secret)
bad = (parts[1][0], parts[1][1] + 1) # one digit wrong when copied by hand
rebuilt = combine([parts[0], bad])
print("rebuilt == original :", rebuilt == secret)
print("original fingerprint:", hashlib.sha256(secret.to_bytes(66, "big")).hexdigest()[:8].upper())
print("rebuilt fingerprint:", hashlib.sha256(rebuilt.to_bytes(66, "big")).hexdigest()[:8].upper())
You should see: a rebuild that succeeded and produced the wrong answer — caught only by the fingerprints:
rebuilt == original : False
original fingerprint: 08A1B781
rebuilt fingerprint: F389B658
Notice what did not happen: no error, no warning, no crash. Splitting has no built-in checksum, so a damaged share rebuilds into a perfectly well-formed secret that opens nothing. That is precisely why step 1 exists. Write the fingerprint next to every share. Without it, you will discover the error on the day you need the backup, which is the one day it cannot be fixed.
If not: if rebuilt == original prints True, the
+ 1 was applied to the share’s x position instead of its value
— it belongs on parts[1][1]. OverflowError: int too big to convert
means the 66 in to_bytes was reduced; that number just has to be
large enough to hold a 521-bit value.
Without scrolling up: you have split your phrase into three shares held in three places, and you keep the fingerprint on your phone. A thief steals the share from your home safe. What have you lost, what have you not lost, and what should you do that same week? Answer: you have lost nothing yet — one share reveals no part of the secret, as step 4 showed — and you have not lost access, because the other two shares still rebuild it. But your redundancy is gone: any single further loss now locks you out permanently, and the thief only needs one more share. The correct response is to rebuild the secret from the two shares you still hold, split it again from scratch into three brand-new shares, and destroy the old set; mixing an old share with a new one will not work, because they lie on different lines.
Now do it without the page: change split so it hands out
five shares instead of three, then confirm that shares 4 and 5 — two you have never
combined before — still rebuild the secret, and that share 3 alone still tells you
nothing. You have just designed your own recovery policy: how many copies exist, and how many
it takes to open them.
Summary
- Lost keys means permanently lost funds — there is no recovery without a backup
- Apply the 3-2-1 rule: 3 copies, 2 mediums, 1 offsite
- Metal storage is the most durable option for seed phrases
- Never store seed phrases digitally in any form
- Distribute copies across different physical locations
- Consider multisig for high-value holdings
- Plan for inheritance so your assets are not lost permanently
With your keys properly secured, learn about the threats and scams targeting crypto users next.