Compare commits

..

2 Commits

Author SHA1 Message Date
Ryan Heywood 8809db6f7f
keyfork-user-guide: add dev guide 2023-10-18 13:24:31 -05:00
Ryan Heywood 9599734bd6
keyfork-user-guide: initial commit 2023-10-18 06:33:50 -05:00
15 changed files with 286 additions and 0 deletions

1
keyfork-user-guide/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
book

View File

@ -0,0 +1,6 @@
[book]
authors = ["ryan"]
language = "en"
multilingual = false
src = "src"
title = "Keyfork User Guide"

View File

@ -0,0 +1,53 @@
# Installing Keyfork
Keyfork is hosted using the Distrust Cargo repository. For the fastest
installation path (this is not recommended), crates may be installed directly
from the Cargo repository:
```sh
cargo install --index https://git.distrust.co/public/_cargo-index keyfork@0.1.0
```
The index is managed by Distrust, but is not signed by developers when commits
are created, so a safer alternative may be to build from source. It is
recommended to perform these operations on a machine dedicated for the purpose
of building Rust binaries, to avoid the risk of building a compromised binary.
```sh
git clone https://git.distrust.co/public/keyfork
cd keyfork
# git checkout keyfork-0.1.0
git verify-commit HEAD
cargo install --locked --path keyfork
```
This will build Keyfork from source, using a local `Cargo.lock` file to ensure
dependencies are not updated automatically.
## Installing Plumbing Binaries
Keyfork offers "plumbing" binaries (as opposed to the "porcelain" `keyfork`)
that offer a smaller [SBOM], allowing users with a smaller feature requirement
to lessen the requirements for code review. Plumbing binaries can be installed
the same way Keyfork is installed, either through the registry or by building
locally. Plumbing binaries are grouped by crates of shared dependencies. For
instance, `keyfork-plumbing` includes all binaries using only shared
dependencies. Eventually, `keyfork-plumbing-openpgp` may contain all
dependencies relevant to OpenPGP (such as the `keyfork-shard` variants,
`keyfork-derive-openpgp`, and `keyfork-provision-openpgp-card`). There may also
be plumbing binaries that exist by themselves, without a plumbing package.
Unfortunately, Cargo offers no convenient way to install a binary from any
package on a workspace, so the information about which package contains which
binary must be known beforehand.
<!-- TODO:
Should plumbing binaries be their own packages?
A convenient command to find the package for a binary should be provided.
-->
```sh
cargo install --index https://git.distrust.co/public/_cargo-index keyfork-plumbing@0.1.0
cargo install --locked --path keyfork-plumbing --bin keyfork-entropy
```
[SBOM]: https://en.wikipedia.org/wiki/SBOM

View File

@ -0,0 +1,14 @@
<!-- vim:set et sts=0 sw=2 ts=2: -->
# Summary
- [Installing Keyfork](./INSTALL.md)
- [Common Usage](./usage.md)
- [Binaries](./bin/index.md)
- [keyfork](./bin/keyfork/index.md)
- [mnemonic](./bin/keyfork/mnemonic/index.md)
- [keyforkd](./bin/keyforkd.md)
- [keyfork-entropy](./bin/keyfork-plumbing/entropy.md)
- [keyfork-mnemonic-from-seed](./bin/keyfork-plumbing/mnemonic-from-seed.md)
- [keyfork-derive-key](./bin/keyfork-derive-key.md)
- [keyfork-derive-openpgp](./bin/keyfork-derive-openpgp.md)
- [Development Guide](./dev-guide/index.md)

View File

@ -0,0 +1 @@
# Binaries

View File

@ -0,0 +1,20 @@
# keyfork-derive-key
Derive a key from a given derivation path.
Requires [`keyforkd`] to be running.
## Arguments
`keyfork-derive-key algorithm path`
* `algorithm`: A supported BIP-0032 algorithm, such as `secp256k1` or `ed25519`
* `path`: A BIP-0032 path, such as `m/44'/0'`
It is recommended to use double quotes when writing a derivation path to avoid
the shell silently ignoring the single quotes in the derivation path.
## Output
Hex-encoded private key. Note that this is not the _extended_ private key, and
can't be used to derive further data.

View File

@ -0,0 +1,30 @@
# keyfork-derive-openpgp
Derive a key from a given derivation path.
Requires [`keyforkd`] to be running.
Because OpenPGP fingerprints are partially based off the time a key was
created, all OpenPGP keys derived using Keyfork use a creation time of UNIX
epoch plus one, to avoid issues of zero being treated as a falsy value.
## Arguments
`keyfork-derive-openpgp path key_format default_userid`
* `path`: A BIP-0032 path, such as `m/7366512'/0'`
* `key_format`: A list of comma-delimited OpenPGP key capabilities; `C` being
certify (required on the first key), `S` being sign, `E` being both
encrypt-for-transport and encrypt-for-storage, and `A` being authenticate.
For OpenPGP cards, an example could be `C,S,E,A`, resulting in one card per
slot and an off-key certifying key.
* `default_userid`: The default OpenPGP UserID, containing any combination of
an email, a full name, and a username, such as `"Ryan Heywood (RyanSquared)
<ryan@distrust.co>"`
It is recommended to use double quotes when writing a derivation path to avoid
the shell silently ignoring the single quotes in the derivation path.
## Output
OpenPGP ASCII armored key, signed to be valid for 24 hours.

View File

@ -0,0 +1,19 @@
# keyfork-entropy
Retrieve system entropy, output in hex format. The machine must be running a
kernel with BLAKE2 entropy support and not be connected to the Internet.
## Arguments
`keyfork-entropy [size=256]`
* `size`: Number of bits, must be divisible by 8
## Variables
- `INSECURE_HARDWARE_ALLOWED=1`: Bypass system validation
- `SHOOT_SELF_IN_FOOT=1`: Bypass system validation
## Output
Hex-encoded system entropy, of length `size / 4`

View File

@ -0,0 +1,11 @@
# keyfork-mnemonic-from-seed
Generate a mnemonic from a seed passed by input.
## Input
Hex-encoded seed, ideally from `keyfork-entropy` or a `keyfork-shard` binary.
## Output
Mnemonic, from 12 to 24 words.

View File

@ -0,0 +1 @@
# keyfork

View File

@ -0,0 +1,22 @@
# `keyfork mnemonic`
Utilities for managing mnemonics.
# `keyfork mnemonic generate`
Generate a mnemonic using various forms of entropy (default: system). Forms of
entropy also include Tarot cards, playing cards, and dice rolls. Because
ensuring entropy is as random as possible while generating mnemonics, and to
ensure the mnemonic itself is not shared to malicious third parties, Keyfork
requires a system be both offline and running an up-to-date kernel before
generating a mnemonic. However, the command may be run with the variable
`INSECURE_HARDWARE_ALLOWED=1` to override system validation.
## Usage
```
% keyfork mnemonic generate
ceiling talent smooth jealous dust render hello resource ripple crucial pepper tribe noble gate shield glad slide document pulse negative spider this fancy seven
% keyfork mnemonic generate --size 128
sustain glory control silk gym argue jaguar citizen remember doctor depth senior
```

View File

@ -0,0 +1,32 @@
# keyforkd
Keyforkd is the backend for deriving data using Keyfork. A mnemonic is loaded
to the server and requests are performed over a UNIX socket. After the server
has validated the request (using whatever approval methods are implemented),
the server will return an extended private key to the client. The extended
private key can then be used either as-is, or to derive further data.
By default, the only validation provided for the request is to ensure the
request contains two indices. By requiring this, `keyforkd` can ensure the
master key is not leaked, and "general" keys (such as `m/44'`, see [BIP-0044])
are not leaked. In the future, `keyforkd` could implement GUI or TTY approval
for users to approve the path requested by the client, such as `m/44'/0'` being
"Bitcoin", or `m/7366512'` being "OpenPGP".
The protocol for the UNIX socket is a framed, [bincode] format. While it is
custom to Keyfork, it is easy to implement. The crate `keyfork-frame` provides
a sync (`Read`, `Write`) and Tokio-compatible async (`AsyncRead`, `AsyncWrite`)
pair of methods for encoding and decoding frames.
The payload, binary data, starts with a big-endian u32 length for the rest of
the data. Next, a SHA-256 hash of the remaining data can be decoded. Lastly,
the data itself is stored as-is. Once the data is retrieved, it may be verified
using the previously-loaded SHA-256 hash.
For encoding the data, the process is reversed. A SHA-256 hash is created, and
the length of the hash and the data is encoded to big-endian and written to the
stream. Then, the hash is written to the stream. Lastly, the data itself is
written as-is to the stream.
[bincode]: https://docs.rs/bincode/latest/bincode/
[BIP-0044]: https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki

View File

@ -0,0 +1 @@
# Chapter 1

View File

@ -0,0 +1,37 @@
# Development Guide
### Binaries - Porcelain and Plumbing
Binaries are split into two categories, porcelain (such as `keyfork`) and
plumbing (just about everything else). Porcelain binaries include what can be
called "the kitchen sink". They offer support for everything - an intuitive
interface, automatic `keyforkd` management, interconnectivity between
derivation utilities and provisioning utilities, and the ability to read from
and write to a configuration file. Plumbing binaries, on the other hand, are
often very rough around the edges and pull in as few dependencies as possible.
Usually, only cryptographic functionality (such as `sequoia-openpgp` or
`dalek-ed25519`) or hardware integration libraries (such as `openpgp-card`) are
included.
### Auditing Dependencies
Dependencies must be reviewed before being added to the repository, and must
not be added for pure convenience. There are few exceptions, such as `clap` and
`thiserror`, which provide derivation macros that are used heavily throughout
`keyfork` and the codebase as a whole. Any dependency added must be reviewed at
least on a surface level to ensure no malicious actions are performed with the
data the library will be responsible for handling. For example, any use of
`std::process` in a crate providing cryptographic functions should be heavily
scrutinized, and any crate that loads arbitrary code or performs networking
requests should have an incredibly important reason for doing so.
Dependencies should be restricted such that the least amount of dead code is
enabled. For instance, a crate such as `keyfork_derive_openpgp` can only make
use of the `ed25519` algorithm, so it exports its own `derive_util` that only
includes the crates required for that library. This can then be used by
programs such as `keyfork-shard`'s OpenPGP mode or `keyfork provision openpgp`
to ensure only the required dependencies are enabled. This reduces the burden
of auditors, but it does mean we can't use projects such as [`hakari`] to
optimize full-project builds.
[`hakari`]: https://docs.rs/cargo-hakari/latest/cargo_hakari/index.html

View File

@ -0,0 +1,38 @@
# Common Usage
Keyfork is a tool to help manage the creation and derivation of binary data
using [BIP-0039] mnemonics. A mnemonic is, in simple terms, a way of encoding a
random number between 128 and 256 bits large, as a list of 12 to 24 words that
can be easily stored or memorized. Once a user has a mnemonic, Keyfork utilizes
[BIP-0032] to derive cryptographic keys, which can be utilized by a variety of
applications.
Once a user has generated a mnemonic with [`keyfork mnemonic generate`], the
mnemonic can be loaded to [`keyforkd`]. This is typically done automatically by
[`keyfork`], but plumbing binaries (commands that are not `keyfork`) require
the server to be started manually.
**NOTE:** Anything beyond this point should be considered Design by
Documentation, and while the commands are not likely to change between now and
when they are released, there is no current stable interface for these
commands, and they may change at any time.
Users can then "provision" keys, or automatically deploy generated keys to
specific endpoints. For OpenPGP smartcards (such as Yubikeys), `keyfork
provision openpgp-card` will automatically derive an OpenPGP key and provision
it to a smartcard. As previously mentioned, if `keyforkd` was not previously
started, a prompt will be provided by the provisioner for the mnemonic, and
`keyforkd` will be started in the background.
Any usage of `keyfork provision` or `keyfork derive` can also be given the
`--save` flag, to modify a `keyfork.toml` file and record when the key was
derived, and for what purpose. This is useful, for instance, with OpenPGP,
where a key may be derived with certain capabilities that may not be remembered
otherwise. Later, the command `keyfork recover` can be used to automatically
re-provision each previously invoked provisioner, and re-derive all previously
invoked derivation, through an interactive prompt.
[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 mnemonic generate`]: ./bin/keyfork/mnemonic/index.md#generate
[`keyforkd`]: ./bin/keyforkd.md