keyfork/README.md

313 lines
9.4 KiB
Markdown

# keyfork #
An opinionated and modular toolchain for generating and managing a wide range
of cryptographic keys offline and on smartcards from a shared [BIP-0039]
mnemonic phrase. BIP-0039 phrases are used to calculate a [BIP-0032] seed,
which is used for hierarchical deterministic key derivation.
**Note:** The difference between the data encoded in a BIP-0039 mnemonic, and
the BIP-0032 seed, is that a BIP-0039 mnemonic of any length can be used to
generate a BIP-0032 seed of a static length (512 bits). Keyfork makes use of a
BIP-0039 mnemonic and does not accept just a BIP-0032 seed - it will be treated
as the entropy provided for a mnemonic, or rejected outright for being of an
invalid size.
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 loading a BIP-0032 seed into an agent to
generate deterministic and unique keypairs. This ensures only the agent has
control over the root seed itself, and other components can request
deterministic data. The BIP-0039 data can also be split using the Keyfork Shard
mechanism, which utilizes Shamir's Secret Sharing to allow "M-of-N" recovery of
the data.
All crate licenses are notated using the "license" field in their respective
Cargo.toml. As a general rule, As a general rule, crates with binaries are
licensed AGPL and crates only used as a library are licensed MIT. Forked
projects retain their original licenses.
## 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 BIP-0039 phrase from OS or physicalized entropy
* Provide and use BIP-0039 passphrase from user supplied entropy
* Read up on [milksad](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](https://git.distrust.co/public/airgap), 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](https://reproducible-builds.org/) 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][gl] and [git-sig][gs].
[gs]: https://git.distrust.co/public/git-sig
[gl]: https://git-lfs.com
1. Clone repo
```sh
git clone https://git.distrust.co/public/keyfork
cd keyfork
```
2. Review binary signatures
```sh
git sig verify
```
Note: See Trust section below for expected keys/signers
3. Install binary
```
make install
```
-->
1. Clone repo
```sh
git clone https://git.distrust.co/public/stack
```
2. Verify Git signatures
```sh
git verify-commit HEAD
```
3. Install binary
```sh
cargo install --path crates/keyfork
```
4. Optionally, build binary for distribution
```sh
cargo build --release --bin keyfork
```
The binary will be made available in `target/release/`.
## Basic Usage
### Personal Setup
On an airgapped system, run the following command to generate a BIP-0039
mnemonic encoding a generated seed:
```sh
keyfork mnemonic generate
```
Once generated, the mnemonic should be written down and stored in a secure
location such as a safe.
<!--
The default format is to use system entropy, but playing cards, tarot cards, or
dice can be used to generate physical entropy
-->
The Keyfork server can be started by running the following command:
```sh
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 card OpenPGP slots 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:
```sh
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:
```sh
keyfork recover shard
```
Otherwise, the Keyfork server can be started by transporting the shards to the
machine using the following command:
```sh
keyfork recover remote-shard
```
Each shard can be transported by running the following command:
```sh
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:
```sh
keyfork derive openpgp "Ryan Heywood (RyanSquared) <ryan@distrust.co>"
```
## Usage
Detailed usage instructions can be found in the [`docs`] mdBook,
which can be opened in-browser by running
`mdbook serve --open docs`.
[`docs`]: /public/keyfork/src/branch/main/docs/src/SUMMARY.md
[BIP-0039]: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
[BIP-0032]: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
<!--
```
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 BIP-0032 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
```
## Examples
#### 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
Requires ```keyfork-pgp``` binary in $PATH
```
$ keyfork pgp --format=sq
$ sq decrypt secret.pgp
```
#### Install deterministic PGP subkeys from agent key to a smartcard
Requires ```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
Requires ```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
Requires ```keyfork-bip44``` binary in $PATH
```
$ keyfork bip44 --path=bitcoin
> m/44'/0'/0'/0/0: 12DefCMhYVv4sBQikyXKMciAoX2wgzhWqb
```
-->