Compare commits
2 Commits
31d1992e16
...
8809db6f7f
Author | SHA1 | Date |
---|---|---|
Ryan Heywood | 8809db6f7f | |
Ryan Heywood | 9599734bd6 |
keyfork-user-guide
.gitignorebook.toml
src
INSTALL.mdSUMMARY.md
bin
chapter_1.mddev-guide
usage.md
|
@ -0,0 +1 @@
|
||||||
|
book
|
|
@ -0,0 +1,6 @@
|
||||||
|
[book]
|
||||||
|
authors = ["ryan"]
|
||||||
|
language = "en"
|
||||||
|
multilingual = false
|
||||||
|
src = "src"
|
||||||
|
title = "Keyfork User Guide"
|
|
@ -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
|
|
@ -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)
|
|
@ -0,0 +1 @@
|
||||||
|
# Binaries
|
|
@ -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.
|
|
@ -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.
|
|
@ -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`
|
|
@ -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.
|
|
@ -0,0 +1 @@
|
||||||
|
# keyfork
|
|
@ -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
|
||||||
|
```
|
|
@ -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
|
|
@ -0,0 +1 @@
|
||||||
|
# Chapter 1
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue