shard-core protects sensitive bytes and recovery phrases with authenticated
encryption, threshold recovery, and fail-closed file handling.
Security status:
0.3.0is the current release and has not received an independent security audit. Tests and AI-assisted review are not a security audit. Use synthetic material for evaluation and rehearse recovery before protecting production secrets.
| Capability | Status |
|---|---|
| ChaCha20-Poly1305 authenticated encryption | Included |
| Scrypt passphrase encryption | Included |
| AEAD plus Shamir threshold protection | Included |
| Corrupt-extra-share recovery and ambiguity detection | Included |
| Fordefi Recovery Phrases workflow | Included |
| Custodian, peer, and multi-party custody guidance | Included |
| Optional SLIP-39 support | .[slip39] extra |
| Reproducible, hash-verified offline bundle pipeline | Included |
| Implicit plaintext output or silent overwrite | Refused |
plaintext
|
| encrypt with random 32-byte data-encryption key (DEK)
v
ChaCha20-Poly1305 --------------------> authenticated ciphertext C
^ |
| |
random DEK -- Shamir split --> K1, K2, ... Kn |
| |
+--> SHRD i = header + Ki + C
Each SHRD artifact contains a unique Shamir key share and the same ciphertext. That duplication is intentional: every valid threshold subset is self-contained. The trade-off is additional storage, not weaker confidentiality.
The plaintext itself is never Shamir-split. A wrong key-share combination fails AEAD authentication instead of returning plausible but incorrect plaintext.
supplied SHRD files
|
v
parse and group candidate sets
|
v
try bounded threshold combinations
|
v
reconstruct DEK -> verify AEAD tag -> plaintext
|
+--> fail closed on corruption or ambiguity
See THREAT_MODEL.md for the security properties, assumptions, and non-goals.
Requires Python 3.9 or newer.
Install the stable release from PyPI:
python3 -m venv .venv
. .venv/bin/activate
python -m pip install 'shard-core==0.3.0'
shard-core --versionTo include optional SLIP-39 support:
python -m pip install 'shard-core[slip39]==0.3.0'To install the same immutable release from source instead:
git clone --branch v0.3.0 --depth 1 \
https://github.com/Protocol-Wealth/shard-core.git
cd shard-core
python3 -m venv .venv
. .venv/bin/activate
python -m pip install .
shard-core --versionFor development:
python -m pip install -e '.[test]'For a hash-locked, network-disabled, rootless Podman build and an installable
offline bundle, follow OFFLINE_BUILD.md. The top-level
install.sh only dispatches to an already built offline bundle; it is not the
quick installer.
shard-core protect \
--threshold 2 \
--shares 3 \
--input secret.bin \
--out-dir shares
shard-core verify-set --require-complete \
shares/share-01.txt \
shares/share-02.txt \
shares/share-03.txt
shard-core recover \
--output recovered.bin \
shares/share-01.txt \
shares/share-03.txtshard-core encrypt --input secret.bin --output secret.shen
shard-core decrypt --input secret.shen --output recovered.binThe commands prompt without echo. For controlled automation, use a private
regular file with --passphrase-file; environment-variable passphrases emit a
warning.
The current source-tree wizard exposes Choose a custody route as an explicit, non-default menu option. The existing commands can also be used directly:
| Route | Capability | shard-core boundary |
|---|---|---|
| CoinCover Key Vault CLI | Locally encrypts the original key file and uploads provider ciphertext | Separate native workflow; do not create SHEN/SHRD first |
| Station70 native Fordefi/Bunker | Uses Fordefi Public Key Upload and a Station70 recovery policy | Separate native workflow; shard-core is not required |
| Station70 Custom Upload | Browser-encrypts supplied text or a file before upload | Separate by default; SHEN/SHRD would be a deliberate nested design |
| Station70 SWAT | Provider-to-provider continuity into a linked standby wallet | Not a SHEN or SHRD file-recovery path |
| External provider or person | Holds one opaque SHEN file and returns it byte-for-byte | Store the wrapping credential on a separate approved path |
| Two or more independent holders | Each holds one SHRD file under an n-of-m policy |
Every holder must confirm exact SHRD acceptance and retrieval |
For example, a 2-of-3 SHRD policy can use the labels protocol,
station70, and trusted-friend, but naming a holder does not establish that
it accepts the artifact. Provider capabilities and release requirements must
be confirmed against current documentation and the applicable agreement.
The project never calls a vendor API or uploads an artifact. See docs/CUSTODY-PATTERNS.md for CoinCover-native, Station70 Bunker and Custom Upload, Nemean, peer-to-peer, tri-party, and nested-provider patterns.
Fordefi lets the operator choose among Public Key Upload, Recovery Phrases, and managed provider or hardware-backed methods.
Fordefi backup method
|
+--> Public Key Upload
| +--> self-managed RSA or YubiKey
| +--> managed CoinCover or Station70 Bunker
| +--> public-key recovery path; shard-core is not required
|
+--> Recovery Phrases
+--> phrase -> SHEN plus separate credential
+--> phrase -> threshold SHRD shares
For the Recovery Phrases path, direct encryption is:
shard-core fordefi encrypt --output protocol-phrase.shen
shard-core fordefi decrypt \
--input protocol-phrase.shen \
--output protocol-phrase.txtFordefi phrase entry is hidden and confirmed twice. Standard entry requires 12
lowercase ASCII words; whitespace is canonicalized without changing spelling,
order, or case. shard-core does not assume a Fordefi phrase is BIP-39.
Follow docs/FORDEFI-DISASTER-RECOVERY.md
for method selection, 2-of-2 phrase custody, external-custodian role checks,
and the final offline Fordefi recovery boundary.
Install .[slip39], then use the explicit slip39 command family for material
independently confirmed to be compatible:
shard-core slip39 split \
--threshold 2 \
--shares 3 \
--bip39-file mnemonic.txt \
--out-dir slip39-shares
shard-core slip39 combine \
--bip39 \
--output recovered-mnemonic.txt \
slip39-shares/share-01.txt \
slip39-shares/share-03.txt- Sensitive recovery and decryption require
--output FILEor deliberate--stdout. - Existing output files are refused unless
--forceis explicit. - Final-component symlinks are refused even with
--force. - Multi-file output is fully preflighted before any share is written.
- New secret files use mode
0600; new private directories use mode0700. - Identical duplicate shares are reported; conflicting duplicates fail.
- Independent complete sets in one recovery invocation fail as ambiguous.
- Recovery combinations are bounded to prevent uncontrolled work.
- Manifests contain artifact hashes and set metadata, never plaintext hashes.
These controls assume a trusted host and controlled parent directories. See THREAT_MODEL.md and CEREMONY.md.
- SHEN v2 stores scrypt parameters, salt, nonce, tag, and ciphertext.
- SHRD v2 stores the authenticated common header, one key share, and ciphertext.
- SHEN v1/v2 and SHRD v1/v2 readers remain supported.
- Display comments and holder labels are not cryptographically authenticated.
Wire-format changes require a separate compatibility and cryptographic review.
- CEREMONY.md: generic safe operator workflow.
- docs/CUSTODY-PATTERNS.md: external custodian, peer, and multi-party patterns.
- docs/FORDEFI-DISASTER-RECOVERY.md: Fordefi-specific workflow.
- OFFLINE_BUILD.md: reproducible verified bundle build.
- THREAT_MODEL.md: assets, adversaries, assumptions, and scope.
- SECURITY.md: vulnerability disclosure and support policy.
- AGENTS.md: canonical rules for AI agents assisting a human;
duplicate
AGENTS.txtandLLMS.txtentry files are intentionally omitted. - CHANGELOG.md: release history and compatibility notes.
- CONTRIBUTING.md: development and review workflow.
- SUPPORT.md: support boundaries and safe issue reporting.
- RELEASING.md: maintainer release procedure.
PYTHONPATH=src python -m unittest discover -s tests -v
PYTHONPATH=src python -O -m unittest discover -s tests -vDual-licensed under Apache-2.0 or MIT-0. See LICENSE and LICENSE-MIT-0.