forked from sneak/hacks
bip85keys: rename from bip85ssh and group commands by key type
The tool will cover more key types than SSH, so the directory, module and binary become bip85keys and the commands are grouped by type: "bip85keys ssh pub|priv|install|ssh" now, "bip85keys age pub|priv" planned. The README states the age derivation (agehd's path in sneak/secret) and that adding a type is one package plus one subcommand. The SSH application id and everything else stay as before. Model: fable-5-1
This commit is contained in:
@@ -1,11 +1,14 @@
|
|||||||
# bip85ssh
|
# bip85keys
|
||||||
|
|
||||||
`bip85ssh` turns a BIP-39 mnemonic (or a BIP-32 `xprv`) into SSH key pairs that
|
`bip85keys` turns a BIP-39 mnemonic (or a BIP-32 `xprv`) into key pairs that can
|
||||||
can be recreated from that secret at any time. The same secret and the same
|
be recreated from that secret at any time. The same secret, key type and index
|
||||||
index always give the same key. Only ed25519 keys are produced.
|
always give the 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
|
||||||
follows 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
|
||||||
|
this PR) and `bip85keys age ...` for age identities (planned, see below).
|
||||||
|
|
||||||
## Derivation
|
## Derivation
|
||||||
|
|
||||||
@@ -15,20 +18,44 @@ The secret is turned into a key like this:
|
|||||||
2. seed -> BIP-32 master key;
|
2. seed -> BIP-32 master key;
|
||||||
3. master key -> 64 bytes of BIP-85 entropy at the path below;
|
3. master key -> 64 bytes of BIP-85 entropy at the path below;
|
||||||
4. entropy -> BIP-85 DRNG (SHAKE256); read 32 bytes;
|
4. entropy -> BIP-85 DRNG (SHAKE256); read 32 bytes;
|
||||||
5. those 32 bytes are the ed25519 seed.
|
5. those 32 bytes become the key in the way the key type needs.
|
||||||
|
|
||||||
The path is:
|
The path is:
|
||||||
|
|
||||||
```
|
```
|
||||||
m/83696968'/592366788'/1822331379'/<n>'
|
m/83696968'/592366788'/<app>'/<n>'
|
||||||
```
|
```
|
||||||
|
|
||||||
- `83696968` is the fixed BIP-85 purpose.
|
- `83696968` is the fixed BIP-85 purpose.
|
||||||
- `592366788` is the vendor id, `sha256("berlin.sneak") & 0x7fffffff`, the same
|
- `592366788` is the vendor id, `sha256("berlin.sneak") & 0x7fffffff`, the same
|
||||||
one `agehd` uses.
|
one `agehd` uses.
|
||||||
- `1822331379` is the application id, `sha256("bip85ssh") & 0x7fffffff`.
|
- `app` is the application id of the key type; each type has its own.
|
||||||
- `n` is the key index: flag `--index` / `-n`, default `0`.
|
- `n` is the key index: flag `--index` / `-n`, default `0`.
|
||||||
|
|
||||||
|
## Giving it the secret
|
||||||
|
|
||||||
|
The secret is never taken as a command-line argument. It is looked for in this
|
||||||
|
order; the first one found wins:
|
||||||
|
|
||||||
|
1. `--mnemonic-file <path>` or `--xprv-file <path>`: 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`.
|
||||||
|
|
||||||
|
If none of these is available and standard input is not a terminal, the tool
|
||||||
|
refuses and exits with status 1.
|
||||||
|
|
||||||
|
Every command takes `--index` / `-n` and the secret flags above, and has
|
||||||
|
`--help`. `bip85keys --version` prints the version set at build time.
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
Test vector, mnemonic
|
Test vector, mnemonic
|
||||||
`abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about`:
|
`abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about`:
|
||||||
|
|
||||||
@@ -37,26 +64,7 @@ index 0: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA1esgfi4OeaywgKh0o5r/8lMOUlUD/N+Yo
|
|||||||
index 1: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB26T7hdDuUF6wfTQ7NpIpyeTgGha4NlhQjaAhap5dqs
|
index 1: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB26T7hdDuUF6wfTQ7NpIpyeTgGha4NlhQjaAhap5dqs
|
||||||
```
|
```
|
||||||
|
|
||||||
## Giving it the secret
|
### `bip85keys ssh pub`
|
||||||
|
|
||||||
The secret is never taken as a command-line argument. It is looked for in this
|
|
||||||
order; the first one found wins:
|
|
||||||
|
|
||||||
1. `--mnemonic-file <path>` or `--xprv-file <path>`: the file holds the secret
|
|
||||||
on one line.
|
|
||||||
2. Environment variable `BIP85SSH_MNEMONIC` or `BIP85SSH_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`.
|
|
||||||
|
|
||||||
If none of these is available and standard input is not a terminal, the tool
|
|
||||||
refuses and exits with status 1.
|
|
||||||
|
|
||||||
## Commands
|
|
||||||
|
|
||||||
Every command takes `--index` / `-n` and the secret flags above, and has
|
|
||||||
`--help`. `bip85ssh --version` prints the version set at build time.
|
|
||||||
|
|
||||||
### `bip85ssh pub`
|
|
||||||
|
|
||||||
Prints one `authorized_keys` line to standard output:
|
Prints one `authorized_keys` line to standard output:
|
||||||
|
|
||||||
@@ -64,16 +72,16 @@ Prints one `authorized_keys` line to standard output:
|
|||||||
ssh-ed25519 <key> <comment>
|
ssh-ed25519 <key> <comment>
|
||||||
```
|
```
|
||||||
|
|
||||||
The comment defaults to `bip85ssh/<n>`; change it with `--comment`.
|
The comment defaults to `bip85keys/ssh/<n>`; change it with `--comment`.
|
||||||
|
|
||||||
### `bip85ssh priv`
|
### `bip85keys 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`.
|
||||||
|
|
||||||
### `bip85ssh install <[user@]host> [-- ssh options...]`
|
### `bip85keys 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:
|
||||||
|
|
||||||
@@ -85,7 +93,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.
|
||||||
|
|
||||||
### `bip85ssh ssh <host> [ssh arguments...]`
|
### `bip85keys ssh ssh <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`
|
||||||
@@ -93,23 +101,40 @@ 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)
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
## Adding a key type
|
||||||
|
|
||||||
|
Adding a key type is one package under `internal/` that turns the 32 derived
|
||||||
|
bytes into that type's key, plus one cobra subcommand under `internal/cli/` that
|
||||||
|
groups its commands.
|
||||||
|
|
||||||
## Errors
|
## Errors
|
||||||
|
|
||||||
Errors go to standard error and the exit status is 1, except for the `ssh`
|
Errors go to standard error and the exit status is 1, except for `ssh ssh`,
|
||||||
command, which passes through `ssh`'s own exit status.
|
which passes through `ssh`'s own exit status.
|
||||||
|
|
||||||
## Building and running
|
## Building and running
|
||||||
|
|
||||||
```
|
```
|
||||||
make build # produces ./bip85ssh
|
make build # produces ./bip85keys
|
||||||
make check # fmt-check, lint (golangci-lint) and tests
|
make check # fmt-check, lint (golangci-lint) and tests
|
||||||
```
|
```
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
```
|
```
|
||||||
bip85ssh pub -n 3
|
bip85keys ssh pub -n 3
|
||||||
bip85ssh priv > ~/.ssh/id_bip85_3
|
bip85keys ssh priv -n 3 > ~/.ssh/id_bip85_3
|
||||||
bip85ssh install -n 3 user@example.com
|
bip85keys ssh install -n 3 user@example.com
|
||||||
bip85ssh ssh -n 3 user@example.com uptime
|
bip85keys ssh ssh -n 3 user@example.com uptime
|
||||||
```
|
```
|
||||||
Reference in New Issue
Block a user