2023-08-16 01:23:15 +00:00
|
|
|
# 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.
|
|
|
|
|
2023-08-16 10:45:40 +00:00
|
|
|
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.
|
2023-08-16 10:43:40 +00:00
|
|
|
|
2023-10-06 21:12:31 +00:00
|
|
|
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.
|
|
|
|
|
2023-09-21 22:30:48 +00:00
|
|
|
## 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.
|
|
|
|
|
2023-09-21 23:08:07 +00:00
|
|
|
## Keyfork Top-Level Binary
|
|
|
|
|
|
|
|
The `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 `keyfork`.
|
|
|
|
|
|
|
|
For instance, the program to generate system entropy is `keyfork-entropy`. It
|
|
|
|
accepts an arbitrary length and spits out a hex-encoded chunk of data. The
|
|
|
|
program to convert that entropy into a seed is `keyfork-mnemonic-from-seed`. It
|
|
|
|
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: `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.
|
|
|
|
|
2023-09-21 22:30:48 +00:00
|
|
|
---
|
|
|
|
|
2023-08-16 01:23:15 +00:00
|
|
|
Note: The following document is all proposed, and not yet implemented.
|
|
|
|
|
|
|
|
## Features
|
|
|
|
|
|
|
|
* Modular
|
|
|
|
* 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
|
|
|
|
* Recoverable
|
|
|
|
* Config file and 24 word mnemonic phrase to recover -all- keys
|
|
|
|
* Unpredictable
|
|
|
|
* Generate a BIP39 phrase from OS entropy
|
|
|
|
* Take BIP39 passphrase from user supplied entropy
|
|
|
|
* Read up on [https://milksad.info](milksad) to understand why this matters!
|
|
|
|
* 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](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
|
|
|
|
```
|
|
|
|
|
2024-01-10 01:39:11 +00:00
|
|
|
## 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
|
|
|
|
```
|
|
|
|
|
2024-01-10 01:41:57 +00:00
|
|
|
Once generated, the mnemonic should be written down and stored in a secure
|
|
|
|
location such as a safe.
|
|
|
|
|
2024-01-10 01:39:11 +00:00
|
|
|
<!--
|
|
|
|
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 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:
|
|
|
|
|
|
|
|
```sh
|
|
|
|
keyfork wizard generate-shard-secret --threshold $N --max $M --keys-per-shard $I > shards.pgp
|
|
|
|
```
|
|
|
|
|
2024-01-10 01:41:57 +00:00
|
|
|
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.
|
|
|
|
|
2024-01-10 01:39:11 +00:00
|
|
|
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>"
|
|
|
|
```
|
|
|
|
|
2023-08-16 01:23:15 +00:00
|
|
|
## Usage
|
|
|
|
|
2024-01-10 01:39:11 +00:00
|
|
|
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`.
|
2023-12-27 19:05:34 +00:00
|
|
|
|
|
|
|
<!--
|
2023-08-16 01:23:15 +00:00
|
|
|
```
|
|
|
|
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
|
|
|
|
```
|
|
|
|
|
|
|
|
## 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
|
|
|
|
```
|
2023-12-27 19:05:34 +00:00
|
|
|
-->
|