|Ryan Heywood ca2ce33d7a|
An opinionated and modular toolchain for generating and managing a wide range of cryptographic keys offline and on smartcards from a shared bip39 mnemonic phrase.
This toolchain uses a bip32 seed loaded into an agent to generate deterministic and unique keypairs. This ensures only the agent has control over the mnemonic itself, and other components can simply request deterministic data.
This repository must not be managed by
cargo-hakari, to ensure each plumbing
binary can be built with as few dependencies and SLOC to review as possible.
Dependencies must not be added to core utilities such as seed generation and
path derivation without a really good reason we can't implement it ourselves,
such as cryptography libraries. For instance,
utilizes cryptography libraries,
thiserror, with the latter two
being audited dependencies. Utilities such as forklets (applications that
use derived data, such as an OpenPGP keychain generator) and the kitchen-sink
keyfork utility may pull in additional dependencies as needed, but should
strive to use the standard library as much as possible. To avoid code reuse,
additional crates (such as the
smex crate) may be used to share functionality
across several crates.
Keyfork Top-Level Binary
keyfork binary is the most user-friendly interface for interacting with
the Keyfork toolchain. It offers commands that should not take any scriptable
input and should not produce any script-readable output. Such operations that
require script compatibility should be made into their own utilities, with the
higher level interface of interacting with them left solely to
For instance, the program to generate system entropy is
accepts an arbitrary length and spits out a hex-encoded chunk of data. The
program to convert that entropy into a seed is
takes entropy from input and converts it into a seed. The combination of the
two, generating entropy and converting it to a mnemonic, is managed through
keyfork mnemonic generate, which can also be used to offer more
options down the line, such as generating a mnemonic from tarot or playing
cards, or dice.
Note: The following document is all proposed, and not yet implemented.
- Standalone binaries can derive/manage keys/config from bip32 root
- Modules handle use cases like ssh, pgp, webauthn, crypto-assets, etc
- Module contract is dead simple and can be written in any language
- Config file and 24 word mnemonic phrase to recover -all- keys
- Generate a BIP39 phrase from OS entropy
- Take BIP39 passphrase from user supplied entropy
- Read up on https://milksad.info to understand why this matters!
- Will exit if network access is detected to force you to keep keys offline
- Helps limit the risk of supply chain attacks
- Intended for use with QubesOS Vault VM, AirgapOS, etc
- Private keys are installed to HSMs/TEEs for use by online machines
These steps will allow you to prove that at least two Distrust engineers signed off on the produced binaries, signaling that they reproduced them from source code and got identical results, in addition to our usual two-party code review processes.
This minimizes a single point of trust (and failure) in our binary release process.
See the Reproducible Builds project for more information on these practices.
We use git for all development, releases, and signing. Unfortunately git has no native method for large file storage or multi-signature workflows so some git add-ons are required.
git clone https://git.distrust.co/public/keyfork cd keyfork
Review binary signatures
git sig verify
Note: See Trust section below for expected keys/signers
keyfork generate [-c,--config=<file>] Generate new mnemonic optionally public keys defined by config keyfork recover [-c,--config=<file>] [-a,--agent] Recover keychain and optionally config defined pubkeys from mnemonic Optionally run a daemon to supply keys to subcommands keyfork version Show version information. keyfork help Show this text. keyfork [command] Commands receive bip32 root as stdin Commands return output and config data as json over stdout back to keyfork keyfork [command] help Show help for a particular sub-command
Generate a new mnemonic to write to paper
$ keyfork generate > milk sad wage cup reward umbrella raven visa give list decorate bulb gold raise twenty fly manual stand float super gentle climb fold park
Recover a mnemonic with a passphrase and spawn agent
$ keyfork recover --agent > mnemonic: ******** > passphrase: ********
Derive deterministic PGP keychain from agent key in default "sq" path
keyfork-pgp binary in $PATH
$ keyfork pgp --format=sq $ sq decrypt secret.pgp
Install deterministic PGP subkeys from agent key to a smartcard
keyfork-pgp binary in $PATH
$ keyfork pgp install --device=nitrokey $ gpg --card-status
Install first deterministic PIV key from agent key to smartcard on slot 1
keyfork-piv binary in $PATH
$ keyfork piv install --device=yubikey --key=1 --slot=1 > Management Key: **** > User Pin: **** > Admin Pin: **** $ ssh-keygen -D "$OPENSC_LIBS/opensc-pkcs11.so" -e
Derive first deterministic BIP44 address for Bitcoin Account 1
keyfork-bip44 binary in $PATH
$ keyfork bip44 --path=bitcoin > m/44'/0'/0'/0/0: 12DefCMhYVv4sBQikyXKMciAoX2wgzhWqb