From 8e24b0ae886117b5d2d8f190026debc5c4acb023 Mon Sep 17 00:00:00 2001 From: clawbot Date: Sun, 6 Sep 2026 14:35:30 +0000 Subject: [PATCH] bip85keys: mnemonic only, and a command that produces it Per sneak: no xprv input. The mnemonic comes from a shell command given as a flag or an environment variable (for example `secret get foo`), from an environment variable holding it, or from a no-echo prompt. The file flag is dropped since the command covers it. Model: fable-5-1 --- bip85keys/README.md | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/bip85keys/README.md b/bip85keys/README.md index b4e4e4c..b32d9c9 100644 --- a/bip85keys/README.md +++ b/bip85keys/README.md @@ -1,8 +1,8 @@ # bip85keys -`bip85keys` turns a BIP-39 mnemonic (or a BIP-32 `xprv`) into key pairs that can -be recreated from that secret at any time. The same secret, key type and index -always give the same key. +`bip85keys` 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. @@ -12,9 +12,9 @@ this PR) and `bip85keys age ...` for age identities (planned, see below). ## Derivation -The secret is turned into a key like this: +The mnemonic is turned into a key like this: -1. mnemonic -> BIP-39 seed (empty passphrase), or the `xprv` is parsed directly; +1. mnemonic -> BIP-39 seed (empty passphrase); 2. seed -> BIP-32 master key; 3. master key -> 64 bytes of BIP-85 entropy at the path below; 4. entropy -> BIP-85 DRNG (SHAKE256); read 32 bytes; @@ -32,22 +32,26 @@ m/83696968'/592366788'/'/' - `app` is the application id of the key type; each type has its own. - `n` is the key index: flag `--index` / `-n`, default `0`. -## Giving it the secret +## Giving it the mnemonic -The secret is never taken as a command-line argument. It is looked for in this +The mnemonic itself is never a command-line argument. It is looked for in this order; the first one found wins: -1. `--mnemonic-file ` or `--xprv-file `: the file holds the secret - on one line. -2. Environment variable `BIP85KEYS_MNEMONIC` or `BIP85KEYS_XPRV`. -3. A prompt on the terminal with echo turned off. The prompt accepts either a - mnemonic or an `xprv`; a value starting with `xprv` is treated as an `xprv`. +1. `--mnemonic-command `: a shell command, run with `sh -c`, whose + 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 + command held in the environment. +3. Environment variable `BIP85KEYS_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 -refuses and exits with status 1. +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 the secret flags above, and has -`--help`. `bip85keys --version` prints the version set at build time. +Every command takes `--index` / `-n` and `--mnemonic-command`, and has `--help`. +`bip85keys --version` prints the version set at build time. ## SSH keys: `bip85keys ssh` @@ -133,7 +137,7 @@ make check # fmt-check, lint (golangci-lint) and tests Examples: ``` -bip85keys ssh pub -n 3 +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 ssh -n 3 user@example.com uptime