1
0
forked from sneak/hacks

keyfunc: age keys, age encrypt and decrypt, and derived mnemonics are in scope

Per sneak. The age commands derive the identity at the generic path and
encrypt or decrypt with it, always including the identity's own
recipient. The mnemonic command derives child mnemonics through BIP-85's
own mnemonic application.

Model: fable-5-1
This commit is contained in:
clawbot
2026-09-07 14:16:29 +00:00
parent b2214ca5c5
commit 7f7c9c67a0

View File

@@ -7,8 +7,10 @@ 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: `keyfunc ssh ...` for ed25519 SSH keys (in
this PR) and `keyfunc age ...` for age identities (planned, see below).
Commands are grouped by what is derived: `keyfunc ssh ...` for ed25519 SSH
keys, `keyfunc age ...` for age identities and for encrypting and decrypting
with them, and `keyfunc mnemonic ...` for child mnemonics derived from the
main one.
## Derivation
@@ -106,15 +108,45 @@ 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: `keyfunc age` (planned)
## age identities: `keyfunc age`
Not in this PR, which delivers the SSH type first; it is the next type to add.
`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
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.
The application number is `657169`, path `m/83696968'/657169'/<n>'`. The 32
bytes from step 4 are clamped as X25519 requires and become an age 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.
### `keyfunc age pub`
Prints the recipient, the `age1...` public key, on one line.
### `keyfunc age priv`
Prints the identity, the `AGE-SECRET-KEY-1...` line, and nothing else.
### `keyfunc age encrypt [-n N] [--to <recipient>...] [-o <file>] [<file>]`
Encrypts the file (or standard input) with age. The recipients are the derived
identity's own recipient, plus any given with `--to`, so the same mnemonic can
always decrypt what it encrypted. Output goes to `-o` or standard output;
`--armor` writes the text form. Nothing is written except the output.
### `keyfunc age decrypt [-n N] [-o <file>] [<file>]`
Decrypts the file (or standard input) with the derived identity. Output goes to
`-o` or standard output. If the identity is not one of the recipients, the tool
says so and exits with status 1.
## Derived mnemonics: `keyfunc mnemonic`
### `keyfunc mnemonic [-n N] [--words 12|18|24]`
Prints a child mnemonic derived from the main one, using BIP-85's own mnemonic
application (number `39`, English, path
`m/83696968'/39'/0'/<words>'/<n>'`, entropy taken as the specification says,
not through step 4). Default 12 words. A child mnemonic is a full mnemonic in
its own right: it can seed another `keyfunc`, another wallet, or `secret`, and
it never has to be written down, since it can be derived again.
## Adding a key type
@@ -141,4 +173,8 @@ 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
keyfunc age pub -n 0
keyfunc age encrypt -n 0 --armor -o notes.age notes.txt
keyfunc age decrypt -n 0 notes.age
keyfunc mnemonic -n 1 --words 24
```