1
0
forked from sneak/hacks

bip85keys: generic derivation path, ssh to, new test vectors

Per sneak: the path carries no vendor id, since this is meant as a
standard others can follow. Application numbers follow BIP-85's own
spelling for RSA: SSH is 838372, age is 657169. The ssh subcommand that
runs the system ssh is now "to". Test vectors recomputed for the new
path. secret's age keys move to this path in a change there.

Model: fable-5-1
This commit is contained in:
clawbot
2026-09-06 22:06:27 +00:00
parent 8e24b0ae88
commit 933fa164c1

View File

@@ -23,13 +23,15 @@ The mnemonic is turned into a key like this:
The path is:
```
m/83696968'/592366788'/<app>'/<n>'
m/83696968'/<app>'/<n>'
```
- `83696968` is the fixed BIP-85 purpose.
- `592366788` is the vendor id, `sha256("berlin.sneak") & 0x7fffffff`, the same
one `agehd` uses.
- `app` is the application id of the key type; each type has its own.
- `app` is the application number of the key type. There is no vendor id: the
path is meant as a standard any implementation can follow, not something tied
to one tool. Each key type's number is spelled the way BIP-85 spells its own
RSA application (`828365` is the ASCII codes of `R`, `S`, `A` written out):
SSH is `838372` (`S` `S` `H`), age is `657169` (`A` `G` `E`).
- `n` is the key index: flag `--index` / `-n`, default `0`.
## Giving it the mnemonic
@@ -55,17 +57,16 @@ Every command takes `--index` / `-n` and `--mnemonic-command`, and has `--help`.
## SSH keys: `bip85keys ssh`
Only ed25519 keys are produced. The application id is `1822331379`,
`sha256("bip85ssh") & 0x7fffffff`, so the path is
`m/83696968'/592366788'/1822331379'/<n>'`. The 32 bytes from step 4 are the
ed25519 seed.
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
seed.
Test vector, mnemonic
`abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about`:
```
index 0: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA1esgfi4OeaywgKh0o5r/8lMOUlUD/N+YoAiC8SNEML
index 1: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB26T7hdDuUF6wfTQ7NpIpyeTgGha4NlhQjaAhap5dqs
index 0: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJZOtOczrc/7CQytcuFwt7s4r8KjkZWkwjLZWBaFKD+7
index 1: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOEWY8+/gmHYVC4u0Y0I4FKs+eVUulTPHfk9VtXw1tMF
```
### `bip85keys ssh pub`
@@ -97,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 ssh <host> [ssh arguments...]`
### `bip85keys 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`
@@ -108,13 +109,12 @@ socket and directory on the way out. The private key is never written to disk.
## age identities: `bip85keys 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 derive exactly what
`sneak/secret` derives with its `agehd` package: application id `733482323`
(`sha256("secret") & 0x7fffffff`), so the path is
`m/83696968'/592366788'/733482323'/<n>'`; the 32 bytes from step 4 are clamped
as X25519 requires and encoded as an `AGE-SECRET-KEY-1...` identity. An age key
from this tool for a given mnemonic and index will equal the one `secret`
derives.
`bip85keys age pub` and `bip85keys 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
vendor-specific path today; for its keys to equal this tool's it moves to this
path, which is a change in `secret`, not here.
## Adding a key type
@@ -124,7 +124,7 @@ groups its commands.
## Errors
Errors go to standard error and the exit status is 1, except for `ssh ssh`,
Errors go to standard error and the exit status is 1, except for `ssh to`,
which passes through `ssh`'s own exit status.
## Building and running
@@ -140,5 +140,5 @@ 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 ssh -n 3 user@example.com uptime
bip85keys ssh to -n 3 user@example.com uptime
```