1
0
forked from sneak/hacks

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
same key.
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.
Commands are grouped by key type: `bip85keys ssh ...` for ed25519 SSH keys (in
this PR) and `bip85keys age ...` for age identities (planned, see below).
Commands are grouped by key type: `keyfunc ssh ...` for ed25519 SSH keys (in
this PR) and `keyfunc age ...` for age identities (planned, see below).
## Derivation
@@ -43,9 +43,9 @@ order; the first one found wins:
standard output is the mnemonic. Example: `--mnemonic-command 'secret get
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.
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.
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.
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.
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
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
```
### `bip85keys ssh pub`
### `keyfunc ssh pub`
Prints one `authorized_keys` line to standard output:
@@ -77,16 +77,16 @@ Prints one `authorized_keys` line to standard output:
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
`-----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
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:
@@ -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,
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
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
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.
`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
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
@@ -130,15 +130,15 @@ which passes through `ssh`'s own exit status.
## Building and running
```
make build # produces ./bip85keys
make build # produces ./keyfunc
make check # fmt-check, lint (golangci-lint) and tests
```
Examples:
```
bip85keys ssh pub -n 3 --mnemonic-command 'secret get foo'
bip85keys ssh priv -n 3 > ~/.ssh/id_bip85_3
bip85keys ssh install -n 3 user@example.com
bip85keys ssh to -n 3 user@example.com uptime
keyfunc ssh pub -n 3 --mnemonic-command 'secret get foo'
keyfunc ssh priv -n 3 > ~/.ssh/id_bip85_3
keyfunc ssh install -n 3 user@example.com
keyfunc ssh to -n 3 user@example.com uptime
```