8.3 KiB
keyfork
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.
Keyfork can be used by organizations and solo users, for the purposes of disaster recovery, cold storage, and reproducibility of private keys and secret data. Keyfork achieves this by using 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 request deterministic data. The seed can be split using the Keyfork Shard mechanism, which utilizes Shamir's Secret Sharing to allow "M-of-N" recovery of the seed.
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.
Dependency Policy
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, keyfork-derive-util
only
utilizes cryptography libraries, serde
, and 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
The keyfork
binary is the most user-friendly interface for interacting with
the Keyfork toolchain. It offers commands that are intended to accept
human-readable input and produce human-readable output, and can be described as
a "Terminal User Interface" rather than a "Command Line Interface". An example
of a keyfork
command would be keyfork wizard generate-shard-secret
, which
will generate a secret, provision smart cards, and export the newly-generated
Shard file. Processes included in the keyfork
binary should not accept
arbitrary strings or numbers, such as manual derivation paths, and instead
should ask for values like "account index" and generate their own magic values
if necessary.
Note: The following features are proposed, and may not yet be implemented.
Features
- Modular
- Standalone binaries can derive/manage keys/config
- Modules handle use cases like ssh, pgp, webauthn, crypto-assets, etc
- Module contract is dead simple and can be written in any language
- Recoverable
- Config file and 24 word mnemonic phrase to recover every key
- Shard mechanism allows for "M-of-N" recovery of seed if lost
- Unpredictable
- Generate a BIP39 phrase from OS or physicalized entropy
- Provide and use BIP39 passphrase from user supplied entropy
- Read up on https://milksad.info to understand why this matters!
- Deterministic
- Given the same seed, repeated derivation requests will be reproducible
- Any secret data can be derived again at any point in the future
- Offline
- 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
Install
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.
To follow these steps please install git-lfs and git-sig.
-
Clone repo
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
-
Install binary
make install
Basic Usage
Personal Setup
On an airgapped system, run the following command to generate a BIP-0039 mnemonic encoding a generated seed:
keyfork mnemonic generate
Once generated, the mnemonic should be written down and stored in a secure location such as a safe.
The Keyfork server can be started by running the following command:
keyfork recover mnemonic
Group Setup
This guide assumes you are sharding to an N
-of-M
system with I
smart
cards per shardholder. The variables will be used in the following commands as
$N
, $M
, and $I
. The smart cards will be factory reset during the process.
On an airgapped system, run the following command to generate a file containing encrypted shards of a generated seed:
keyfork wizard generate-shard-secret --threshold $N --max $M --keys-per-shard $I --output shards.pgp
Once generated, the shards file can be safely stored in any location, as the
only information that can be obtained from the shard file is the $N
value.
If all shardholders are physically present, the Keyfork server can be started by running the following command:
keyfork recover shard
Otherwise, the Keyfork server can be started by transporting the shards to the machine using the following command:
keyfork recover remote-shard
Each shard can be transported by running the following command:
keyfork shard transport shard.pgp
Deriving Keys
Keys can be derived from Keyfork using the keyfork derive
command, such as
the following command for an OpenPGP certificate with one of each subkey:
keyfork derive openpgp "Ryan Heywood (RyanSquared) <ryan@distrust.co>"
Usage
Detailed usage instructions can be found in the keyfork-user-guide
mdBook,
which can be opened in-browser by running
mdbook serve --open keyfork-user-guide
.