A command-line tool for splitting secrets using Shamir's Secret Sharing with optional PGP encryption and BIP39 mnemonic support.
- Shamir Secret Sharing: Split secrets with configurable threshold (t) and total shares (n)
- PGP Encryption: Encrypt shares to individual recipients using OpenPGP public keys
- BIP39 Mnemonic Support: Generate and convert 24-word mnemonic phrases for 32-byte secrets
- Stdin/Stdout Interface: Easy piping and automation
- Non-Interactive: Suitable for scripts and automated workflows
- Secure Sharing: Encrypts secrets with XSalsa20-Poly1305 before splitting the encryption key
git clone https://github.com/chainwayxyz/secret-sharing.git
cd secret-sharing
cargo build --release
./target/release/secret-sharing --helpshamirsecretsharing- Shamir secret sharing implementationrand- Cryptographic random number generationsequoia-openpgp- OpenPGP implementation (PGP encryption)crypto_secretbox- XSalsa20-Poly1305 authenticated encryptionchrono- Timestamp generation for filenamesbip39- BIP39 mnemonic phrase generation and parsingclap- CLI parsinganyhow- Error handlinghex- Hex encoding/decoding
Split a secret into shares without encryption:
# From random bytes
openssl rand -hex 32 | secret-sharing share -t 2 -n 3
# Output (hex-encoded shares to stdout):
017276e586b8a646033226dee295250e0f110f8fa537d2f02cd67f33311fdd759f0b700b34876eb...
024c0ca665303e8a1a395e7db2d962d0700e2ab65015c766a519de6fe43860c88d0b700b34876eb...
03e1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890ab...
# Save shares to file
openssl rand -hex 32 | secret-sharing share -t 2 -n 3 > shares.txt
# Reconstruct from any 2 shares
head -2 shares.txt | secret-sharing reconstruct -t 2 --hexFirst, export PGP public keys to files:
# Export public keys from your GPG keyring
gpg --armor --export [email protected] > alice.asc
gpg --armor --export [email protected] > bob.asc
gpg --armor --export [email protected] > charlie.asc# Split secret and encrypt to recipients
cat wallet.dat | secret-sharing share \
-k alice.asc,bob.asc,charlie.asc \
-t 2 -n 3
# Output (files created with threshold, total, and timestamp in filename):
share_01_of_03_t2_for_alice.asc_20251112_180320.pgp
share_02_of_03_t2_for_alice.asc_20251112_180320.pgp
share_03_of_03_t2_for_charlie.asc_20251112_180320.pgp
# Or specify output directory (created automatically if doesn't exist):
cat wallet.dat | secret-sharing share \
-k alice.asc,bob.asc,charlie.asc \
-t 2 -n 3 \
--out backup_shares
# Output:
backup_shares/share_01_of_03_t2_for_alice.asc_20251112_180320.pgp
backup_shares/share_02_of_03_t2_for_bob.asc_20251112_180320.pgp
backup_shares/share_03_of_03_t2_for_charlie.asc_20251112_180320.pgpRecipients decrypt their shares and reconstruct:
# Each recipient decrypts their share (will prompt for passphrase)
gpg -d share_01_of_03_t2_for_alice.asc_20251112_180320.pgp > share1.txt
gpg -d share_02_of_03_t2_for_bob.asc_20251112_180320.pgp > share2.txt
# Any 2 shares (threshold=2) can reconstruct the original secret
cat share1.txt share2.txt | secret-sharing reconstruct -t 2 > wallet.datGenerate a mnemonic for backup:
# Generate 32-byte secret and display mnemonic
openssl rand -hex 32 | secret-sharing share -t 2 -n 3 --mnemonic > shares.txt
# Output to stderr:
# Mnemonic: park system enable actress february smart husband inner bean session...
# Save mnemonic separately
openssl rand -hex 32 | secret-sharing share -t 2 -n 3 --mnemonic 2> mnemonic.txt > shares.txtConvert mnemonic back to secret:
# Convert 24-word mnemonic to 32-byte secret (hex output)
echo "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art" | \
secret-sharing mnemonic-to-secret
# Output:
# 0000000000000000000000000000000000000000000000000000000000000000
# Use in workflow
echo "your 24 words here" | \
secret-sharing mnemonic-to-secret | \
secret-sharing share -t 2 -n 3
# Get raw bytes instead of hex
echo "your mnemonic" | secret-sharing mnemonic-to-secret --raw > secret.binSplit a secret into shares.
secret-sharing share -t <threshold> -n <total> [OPTIONS]Options:
-t, --threshold <N>: Minimum shares needed to reconstruct (required)-n, --total <N>: Total number of shares to create (required)-k, --keys <FILES>: Comma-separated PGP public key files (optional)-m, --mnemonic: Display BIP39 mnemonic (requires exactly 32 bytes input)-o, --out <DIR>: Output directory for encrypted files (created if doesn't exist)
Input: Secret from stdin (raw bytes or 64-char hex string for 32 bytes)
Output:
- Without
-k: Hex shares to stdout (one per line) - With
-k: Encrypted.pgpfiles created, filenames printed to stdout
Filename Format: share_XX_of_YY_tZ_for_<recipient>_<timestamp>.pgp
XX= Share number (01, 02, 03...)YY= Total sharesZ= Threshold<recipient>= Sanitized key identifier<timestamp>= YYYYMMDD_HHMMSS
Reconstruct a secret from shares.
secret-sharing reconstruct -t <threshold> [--hex]Options:
-t, --threshold <N>: Threshold value used during sharing (required)--hex: Output as hex instead of raw bytes
Input: Hex-encoded shares from stdin, one per line (blank lines and # comments ignored). Each encrypted share includes a trailing newline for easy concatenation.
Output: Reconstructed secret to stdout
Convert a BIP39 mnemonic phrase (24 words) to a 32-byte secret.
secret-sharing mnemonic-to-secret [--raw]Options:
--raw: Output raw bytes (default: hex output)
Input: BIP39 mnemonic phrase from stdin
Output: 32-byte secret to stdout (hex by default)
This implementation uses proper Shamir Secret Sharing with encryption, following the approach used in the reference implementation:
- A random 32-byte encryption key is generated for each secret
- The key is split using Shamir's Secret Sharing algorithm
- The actual secret is encrypted with XSalsa20-Poly1305
- Each share contains:
[keyshare (33 bytes)] + [encrypted secret]
This ensures that:
- Individual shares reveal nothing about the original secret
- Only combining threshold shares reconstructs the encryption key
- The encryption key is used to decrypt the ciphertext
- Meets true secret sharing security requirements
This tool uses Sequoia-OpenPGP, a modern PGP implementation that:
- Properly selects encryption-capable subkeys
- Supports modern PGP standards
- Provides better security and performance
The tool automatically uses encryption-capable subkeys when available, ensuring compatibility with standard GPG key structures where:
- Primary key is marked for certification
[C] - Subkeys are marked for signing
[S], encryption[E], or authentication[A]
# Export public keys
gpg --armor --export [email protected] > alice.asc
gpg --armor --export [email protected] > bob.asc
gpg --armor --export [email protected] > charlie.asc
# Split and encrypt wallet to output directory
cat wallet.dat | secret-sharing share \
-k alice.asc,bob.asc,charlie.asc \
-t 2 -n 3 \
--out wallet_backup
# Files created in wallet_backup/:
# share_01_of_03_t2_for_alice.asc_20251112_180320.pgp
# share_02_of_03_t2_for_bob.asc_20251112_180320.pgp
# share_03_of_03_t2_for_charlie.asc_20251112_180320.pgp# Decrypt shares (each person with their private key)
gpg -d wallet_backup/share_01_of_03_t2_for_alice.asc_20251112_180320.pgp > share1.txt
gpg -d wallet_backup/share_02_of_03_t2_for_bob.asc_20251112_180320.pgp > share2.txt
# Reconstruct wallet (need 2 out of 3 shares, as threshold=2)
cat share1.txt share2.txt | secret-sharing reconstruct -t 2 > wallet.dat# Generate secret and save both mnemonic and shares
openssl rand -hex 32 | \
secret-sharing share -t 2 -n 3 --mnemonic \
2> backup-mnemonic.txt \
> backup-shares.txt
# Later, recover secret from mnemonic
cat backup-mnemonic.txt | \
sed 's/Mnemonic: //' | \
secret-sharing mnemonic-to-secretRun the full test suite:
cargo testTest coverage includes:
- Unit tests for core crypto functions
- Integration tests for CLI workflows
- PGP encryption and decryption tests
- BIP39 mnemonic generation and parsing tests
- Share/reconstruct roundtrip tests
This implementation is inspired by and follows the cryptographic approach of dsprenkels/sss-cli