keyfunc: the tool's name, chosen by sneak

The name says what the tool is: a key is a function of the mnemonic and
an index, computed when asked for and stored nowhere. Directory, module,
binary and environment variables take it.

Model: fable-5-1
This commit is contained in:
clawbot
2026-09-07 13:29:02 +00:00
parent 933fa164c1
commit b2214ca5c5

View File

@@ -1,14 +1,14 @@
# bip85keys # keyfunc
`bip85keys` turns a BIP-39 mnemonic into key pairs that can be recreated from `keyfunc` turns a BIP-39 mnemonic into key pairs that can be recreated from
that mnemonic at any time. The same mnemonic, key type and index always give the that mnemonic at any time. The same mnemonic, key type and index always give the
same key. same key.
It uses the BIP-85 entropy deriver from `git.eeqj.de/sneak/secret/pkg/bip85` and It uses the BIP-85 entropy deriver from `git.eeqj.de/sneak/secret/pkg/bip85` and
takes the same steps as that repository's `agehd` package. takes the same steps as that repository's `agehd` package.
Commands are grouped by key type: `bip85keys ssh ...` for ed25519 SSH keys (in Commands are grouped by key type: `keyfunc ssh ...` for ed25519 SSH keys (in
this PR) and `bip85keys age ...` for age identities (planned, see below). this PR) and `keyfunc age ...` for age identities (planned, see below).
## Derivation ## Derivation
@@ -43,9 +43,9 @@ order; the first one found wins:
standard output is the mnemonic. Example: `--mnemonic-command 'secret get standard output is the mnemonic. Example: `--mnemonic-command 'secret get
foo'`. Whitespace around the output is dropped. If the command exits with a foo'`. Whitespace around the output is dropped. If the command exits with a
non-zero status, the tool prints its standard error and exits with status 1. non-zero status, the tool prints its standard error and exits with status 1.
2. Environment variable `BIP85KEYS_MNEMONIC_COMMAND`: the same, as a shell 2. Environment variable `KEYFUNC_MNEMONIC_COMMAND`: the same, as a shell
command held in the environment. command held in the environment.
3. Environment variable `BIP85KEYS_MNEMONIC`: the mnemonic itself. 3. Environment variable `KEYFUNC_MNEMONIC`: the mnemonic itself.
4. A prompt on the terminal with echo turned off. 4. A prompt on the terminal with echo turned off.
If none of these is available and standard input is not a terminal, the tool If none of these is available and standard input is not a terminal, the tool
@@ -53,9 +53,9 @@ refuses and exits with status 1. A mnemonic that fails the BIP-39 checksum is
refused with a message saying so. refused with a message saying so.
Every command takes `--index` / `-n` and `--mnemonic-command`, and has `--help`. Every command takes `--index` / `-n` and `--mnemonic-command`, and has `--help`.
`bip85keys --version` prints the version set at build time. `keyfunc --version` prints the version set at build time.
## SSH keys: `bip85keys ssh` ## SSH keys: `keyfunc ssh`
Only ed25519 keys are produced. The application number is `838372`, so the Only ed25519 keys are produced. The application number is `838372`, so the
path is `m/83696968'/838372'/<n>'`. The 32 bytes from step 4 are the ed25519 path is `m/83696968'/838372'/<n>'`. The 32 bytes from step 4 are the ed25519
@@ -69,7 +69,7 @@ index 0: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJZOtOczrc/7CQytcuFwt7s4r8KjkZWkwjL
index 1: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOEWY8+/gmHYVC4u0Y0I4FKs+eVUulTPHfk9VtXw1tMF index 1: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOEWY8+/gmHYVC4u0Y0I4FKs+eVUulTPHfk9VtXw1tMF
``` ```
### `bip85keys ssh pub` ### `keyfunc ssh pub`
Prints one `authorized_keys` line to standard output: Prints one `authorized_keys` line to standard output:
@@ -77,16 +77,16 @@ Prints one `authorized_keys` line to standard output:
ssh-ed25519 <key> <comment> ssh-ed25519 <key> <comment>
``` ```
The comment defaults to `bip85keys/ssh/<n>`; change it with `--comment`. The comment defaults to `keyfunc/ssh/<n>`; change it with `--comment`.
### `bip85keys ssh priv` ### `keyfunc ssh priv`
Prints the unencrypted private key in OpenSSH format (the Prints the unencrypted private key in OpenSSH format (the
`-----BEGIN OPENSSH PRIVATE KEY-----` block that `ssh` reads) to standard output `-----BEGIN OPENSSH PRIVATE KEY-----` block that `ssh` reads) to standard output
and nothing else, so it can be redirected into a file. The key's comment is the and nothing else, so it can be redirected into a file. The key's comment is the
same as for `pub`. same as for `pub`.
### `bip85keys ssh install <[user@]host> [-- ssh options...]` ### `keyfunc ssh install <[user@]host> [-- ssh options...]`
Runs the system `ssh` to the host and, on the host: Runs the system `ssh` to the host and, on the host:
@@ -98,7 +98,7 @@ It then prints `added` or `already present`. How this `ssh` connection
authenticates is up to the user's normal `ssh` setup (existing keys, agent, authenticates is up to the user's normal `ssh` setup (existing keys, agent,
password). Anything after `--` is passed to `ssh` unchanged. password). Anything after `--` is passed to `ssh` unchanged.
### `bip85keys ssh to <host> [ssh arguments...]` ### `keyfunc ssh to <host> [ssh arguments...]`
Derives the key, serves it from an SSH agent that runs inside the tool on a unix Derives the key, serves it from an SSH agent that runs inside the tool on a unix
socket in a new private `0700` temporary directory, then runs the system `ssh` socket in a new private `0700` temporary directory, then runs the system `ssh`
@@ -106,10 +106,10 @@ with `-o IdentityAgent=<that socket>` followed by the host and all remaining
arguments unchanged. The tool exits with `ssh`'s exit status and removes the arguments unchanged. The tool exits with `ssh`'s exit status and removes the
socket and directory on the way out. The private key is never written to disk. socket and directory on the way out. The private key is never written to disk.
## age identities: `bip85keys age` (planned) ## age identities: `keyfunc age` (planned)
Not in this PR, which delivers the SSH type first; it is the next type to add. Not in this PR, which delivers the SSH type first; it is the next type to add.
`bip85keys age pub` and `bip85keys age priv` will use application number `keyfunc age pub` and `keyfunc age priv` will use application number
`657169`, path `m/83696968'/657169'/<n>'`; the 32 bytes from step 4 are clamped `657169`, path `m/83696968'/657169'/<n>'`; the 32 bytes from step 4 are clamped
as X25519 requires and encoded as an `AGE-SECRET-KEY-1...` identity, the same as X25519 requires and encoded as an `AGE-SECRET-KEY-1...` identity, the same
steps `sneak/secret` takes in its `agehd` package. `secret` derives at a steps `sneak/secret` takes in its `agehd` package. `secret` derives at a
@@ -130,15 +130,15 @@ which passes through `ssh`'s own exit status.
## Building and running ## Building and running
``` ```
make build # produces ./bip85keys make build # produces ./keyfunc
make check # fmt-check, lint (golangci-lint) and tests make check # fmt-check, lint (golangci-lint) and tests
``` ```
Examples: Examples:
``` ```
bip85keys ssh pub -n 3 --mnemonic-command 'secret get foo' keyfunc ssh pub -n 3 --mnemonic-command 'secret get foo'
bip85keys ssh priv -n 3 > ~/.ssh/id_bip85_3 keyfunc ssh priv -n 3 > ~/.ssh/id_bip85_3
bip85keys ssh install -n 3 user@example.com keyfunc ssh install -n 3 user@example.com
bip85keys ssh to -n 3 user@example.com uptime keyfunc ssh to -n 3 user@example.com uptime
``` ```