v0.3.3 -- Shamir's Secret Sharing for Seed Phrases
What n-of-m does and why it exists.
n-of-m is a client-side tool for splitting cryptocurrency seed phrases into multiple shares using Shamir's Secret Sharing. Instead of storing a single seed phrase in one location (a single point of failure), you split it into N shares and require any M of them to reconstruct the original.
A 3-of-5 split creates 5 share cards. Any 3 of those cards can recover your seed phrase. Losing 1 or 2 cards does not compromise your secret, and no individual card reveals any information about the original phrase.
All operations run in your browser. No data is ever sent to any server.
Each share is encoded as a QR code on a printable card for physical storage.
Fewer than the threshold number of shares reveal zero information about the secret.
Optionally store share sets locally with AES-256-GCM encryption.
The five-phase workflow from generation to recovery.
Create or import a BIP39 mnemonic seed phrase (12-24 words).
Configure your Shamir threshold (e.g., 2-of-3) and split the secret into shares.
Export share cards as PDF, HTML, or PNG. Each card contains a QR code encoding one share.
Distribute printed share cards to separate physical locations (safe deposit boxes, trusted parties).
Scan or upload the threshold number of shares to reconstruct the original seed phrase.
Step-by-step walkthrough of the 7-step wizard.
Select the mnemonic length: 12, 15, 18, 21, or 24 words. Longer mnemonics provide more entropy (128-256 bits). 24 words (256 bits) is recommended for maximum security.
Entropy is generated from crypto.getRandomValues() (your browser's cryptographically secure random number generator). You can optionally add mouse-movement entropy which is mixed in via SHA-256.
The BIP39 mnemonic is generated from the entropy. You can also paste an existing mnemonic if you want to split an already-existing seed phrase. The checksum is validated automatically.
Choose the HD wallet derivation path. Supports MetaMask (m/44'/60'/0'/0/{index}) and Ledger (m/44'/60'/{index}'/0/0) paths. This determines which addresses are derived from your seed.
Preview the Ethereum addresses derived from your mnemonic. Verify these match your wallet to confirm the seed phrase is correct before splitting.
Set the total number of shares (N) and the reconstruction threshold (M). The threshold must be at least 2 and at most equal to the total shares. You can also set a wallet name, optional PIN, and optional BIP39 passphrase.
Preview all share cards before exporting. Download as PDF, print directly, or save to the local encrypted vault. Each card shows the share QR code, wallet name, share index, threshold info, and derived addresses.
How to reconstruct your seed phrase from shares.
Collect at least the threshold number of share cards. For a 3-of-5 split, you need any 3 of the 5 cards.
Use your device camera to scan QR codes from printed cards, or upload previously exported files.
Once enough shares are loaded, the app reconstructs the original mnemonic using Lagrange interpolation over GF(2^8).
Local encrypted storage for share sets and wallet configurations.
The vault stores share sets in your browser's IndexedDB, encrypted with AES-256-GCM. Data never leaves your device. The vault is optional -- you can use the app purely for generating and printing share cards without storing anything locally.
Share sets, wallet names, derivation paths, address lists, and Shamir configuration are stored together.
AES-256-GCM with a browser-generated master key. Optional password protection via PBKDF2-SHA256 (100k iterations).
Export vault contents as PDF, HTML, JSON, or PNG. Multiple formats for redundancy and compatibility.
Import share data from HTML files, JSON backups, or QR code images to rebuild vault entries.
Comparison of available export formats and when to use each.
| Format | Contents | Best For | Notes |
|---|---|---|---|
| Full-page share cards with QR codes, addresses, metadata | Printing physical cards for secure storage | One card per page. Rendered client-side via html2canvas + jsPDF. | |
| HTML | Self-contained share card files with embedded QR codes and styles | Offline archival, sharing via USB drive | Opens in any browser. No dependencies. Can be used as recovery input. |
| JSON | Structured vault data (share sets, configs, addresses) | Backup and restore of full vault state | Machine-readable. Includes all metadata. Password-protected export available. |
| PNG | Single QR code encoding the full vault configuration | Quick backup to image, scanning between devices | Scan with any QR reader. Limited by QR capacity for large vaults. |
For maximum resilience, export in multiple formats. Print PDF cards for physical storage, keep an HTML copy on an offline USB drive, and store a JSON backup in a separate secure location.
Recommendations for threshold selection, storage, and operational security.
| Configuration | Tolerance | Use Case |
|---|---|---|
| 2-of-3 | Lose 1 share | Personal use. Simple setup. Keep one share at home, one in a safe deposit box, one with a trusted person. |
| 3-of-5 | Lose 2 shares | Higher security. Distribute across more locations. Good balance of redundancy and threshold difficulty. |
| 4-of-7 | Lose 3 shares | Organizational use or high-value assets. Requires coordination of 4 parties/locations for recovery. |
Separate locations. Store each share card in a different physical location. The security of Shamir's scheme depends on shares not being co-located.
Protect from elements. Laminate printed cards or use waterproof sleeves. Paper degrades with moisture, sunlight, and heat.
Label clearly. Mark each card with the share index (e.g., "Share 2 of 5") and the wallet name so you know which set it belongs to.
Never store digitally long-term. Print your share cards and then delete any digital copies. Digital files can be copied, exfiltrated, or compromised. Physical cards in separate locations provide stronger security guarantees.
Test recovery before relying on shares. After splitting, immediately test that you can reconstruct the seed from the threshold number of shares. Do not trust untested backups.
Use an air-gapped device. For high-value seeds, run the app on a device that has never been and will never be connected to the internet. Use the standalone HTML download or install as a PWA while offline.
Clear browser data after use. Use Settings → Clear All Data to remove any locally stored vault data, or use a private/incognito window.
Verify addresses before splitting. In Step 5 of the wizard, confirm the derived addresses match your wallet. Splitting the wrong seed phrase is an expensive mistake.
Cryptographic implementation details and trust assumptions.
The app makes zero network requests after initial load. All cryptographic operations -- key generation, secret splitting, address derivation, encryption -- run entirely in your browser. There is no server, no API, no telemetry. Verify this by checking the Network tab in your browser's developer tools.
Implemented over the Galois field GF(2^8). The secret is split byte-by-byte using random polynomials of degree t-1 where t is the threshold. Reconstruction uses Lagrange interpolation. The scheme is information-theoretically secure: fewer than t shares reveal exactly zero information about the secret, regardless of computational power.
AES-256-GCM authenticated encryption. The 256-bit master key is generated from the browser's CSPRNG (crypto.getRandomValues()) and stored in IndexedDB. GCM mode provides both confidentiality and integrity -- any tampering with the ciphertext is detected and rejected.
PBKDF2-SHA256 with 100,000 iterations for vault password hashing. Each password is salted with a random 16-byte value to prevent rainbow table attacks.
BIP39 mnemonic generation with configurable word counts (128-256 bits of entropy). BIP44 hierarchical deterministic key derivation. Supports MetaMask and Ledger derivation path schemes.
Primary entropy: crypto.getRandomValues() (browser CSPRNG, seeded from OS entropy pool). Optional supplemental entropy from mouse movement, mixed via SHA-256. The CSPRNG alone is considered sufficient for all security levels.
Common questions and answers.
As long as you still have at least the threshold number of shares, you can recover your seed phrase. For example, in a 3-of-5 split, losing 2 shares still leaves you with 3 -- enough to reconstruct. If you drop below the threshold, recovery is mathematically impossible.
No. The threshold is baked into the mathematical structure of the shares. To change the threshold, recover the original seed phrase and create a new split with the desired configuration. Destroy the old share cards afterward.
Yes. After the first visit, the service worker caches all assets locally. The app works fully offline as a Progressive Web App (PWA). You can also download the standalone HTML file from Settings for a completely self-contained offline copy.
No. Shamir's Secret Sharing is information-theoretically secure. An attacker with t-1 shares has exactly as much information about the secret as someone with zero shares. This holds regardless of the attacker's computational resources.
The app generates standard BIP39 mnemonics and derives Ethereum (EVM) addresses via BIP44. The seed phrase itself is blockchain-agnostic -- the same mnemonic can be imported into wallets for Bitcoin, Ethereum, Solana, and other BIP39-compatible chains.
No. The vault is encrypted with a browser-generated master key by default. The password adds an additional layer -- it derives a wrapping key via PBKDF2 that encrypts the master key. Without a password, anyone with access to your browser's IndexedDB could decrypt the vault.
The Shamir splitting operates on arbitrary byte sequences, but the app's UI is designed around BIP39 seed phrases. The mnemonic step expects valid BIP39 word sequences with correct checksums. For arbitrary secret splitting, a general-purpose Shamir tool would be more appropriate.
The source code is available on GitHub. For maximum assurance, clone the repository, audit the code, build locally, and run on an air-gapped device. The standalone HTML export contains all code inline for easy review.
Common issues and how to resolve them.
The QR scanner library hides the native video element for Safari compatibility. The app renders the camera feed to a canvas element instead. If the canvas remains blank:
Ensure camera permissions are granted in your browser settings.
On iOS Safari, the page must be served over HTTPS (or localhost).
Close other apps using the camera, then reload the page.
The service worker may be serving cached assets. To force a refresh:
Open DevTools → Application → Service Workers → click "Unregister".
Clear browser cache (Settings → Clear browsing data → Cached images and files).
Close all tabs for the app, then reopen.
PDF generation uses html2canvas to render share cards as images. On some mobile browsers, canvas rendering can fail silently.
Try exporting as HTML instead -- it produces a lighter file with no canvas dependency.
On mobile, ensure the browser tab is in the foreground during export.
Desktop Chrome/Edge produce the most reliable PDF output.
QR scanning depends on print quality and lighting. If codes are not being detected:
Ensure the print is high-resolution (at least 300 DPI). Inkjet prints can blur fine QR modules.
Avoid lamination with high gloss -- matte lamination reduces glare for camera scanning.
If camera scanning fails, upload the HTML or PNG file directly instead.
The vault master key is stored in IndexedDB. Some browsers clear IndexedDB during major updates or storage pressure events. If your password no longer decrypts the vault:
The vault data may be permanently lost if the master key was cleared.
Recover from your physical share cards or exported backup files (HTML, JSON, PNG).
This is why exporting physical backups is critical -- the browser vault is a convenience feature, not a primary backup.
If the reconstructed seed phrase doesn't match your original:
Verify all scanned shares belong to the same share set (same wallet name and share ID).
Mixing shares from different splits produces a valid but incorrect mnemonic with no error indication -- this is inherent to Shamir's scheme.
Check the derived addresses against your wallet to confirm the reconstruction is correct.
Architecture overview and local development setup for contributors.
git clone https://github.com/tankbottoms/n-of-m-web.git cd n-of-m-web npm install npm run devDev server runs at http://localhost:5173 with hot module replacement.
SvelteKit 2 with Svelte 5 runes ($state, $derived, $props). Static adapter for deployment -- no server-side rendering.
Web Crypto API for AES-GCM and PBKDF2. ethers.js for BIP39/BIP44 derivation. Custom GF(2^8) implementation for Shamir splitting.
QRious for QR generation. qr-scanner and jsQR for decoding (camera and static image). Tiled scanning for multi-QR PDFs.
html2canvas + jsPDF via html2pdf.js for client-side PDF generation. CSS @page and page-break directives for print layout.
npm run build npm run previewBuilds to .svelte-kit/output. Deployed automatically to Vercel on push to main. Also deployed to Cloudflare Pages.
npm test -- Vitest-based tests for core crypto logicnpx playwright test -- Browser automation testsnpx svelte-check -- TypeScript type validation