Commit Graph
12 Commits
Author SHA1 Message Date
clawbot a08eb28359 End the mnemonic prompt at end of input (closes #78)
check / check (push) Canceled after 0s
term.ReadPassword reads the terminal with a raw read that returns 0
bytes at the end of input and takes that as nothing yet, so Ctrl-D at
the prompt did nothing. On the Unix systems the prompt now sets the
terminal as ReadPassword does and reads the line from standard input,
which reports the end of input; elsewhere, such as Windows, it still
uses ReadPassword. Ctrl-D with nothing typed gives an empty mnemonic,
refused with status 1, and the terminal settings are put back. A test
types Ctrl-D at the prompt on a pseudo-terminal.

Unverified: the prompt was run only on Linux; other systems were built.
Deviation: a Ctrl-H byte is no longer a backspace at the prompt.

Model: opus-5-5
Co-authored-by: clawbot <sneak+clawbot@sneak.cloud>
2026-10-14 23:35:24 +02:00
clawbot 2fbc32fe75 Check the -o path before looking for the mnemonic (closes #87)
check / check (push) Canceled after 0s
age encrypt and age decrypt looked at the -o path only after the
mnemonic had been obtained, so a path that could never be written
still prompted for the mnemonic or ran the mnemonic command. Both now
refuse, before the key is derived, an -o path that is a directory or a
symlink to one, whose directory is missing or is not a directory, or
that is a symlink pointing at nothing. The check creates nothing;
output still looks at the path when it writes, so the file beside the
target is made when it was before. The README names the -o path among
what is checked first.

Left out: a directory the tool may not write to is found only when it
writes.

Model: opus-5-5
Co-authored-by: clawbot <sneak+clawbot@sneak.cloud>
2026-10-14 23:07:07 +02:00
clawbot f1e27814cd Read the text form with blank lines in front, as age does (closes #77)
check / check (push) Canceled after 0s
age decrypt took the text form only when the file began exactly with
-----BEGIN AGE ENCRYPTED FILE-----, so a blank line in front made it
read the file as the binary form and refuse it. It now looks for that
line past up to 1024 bytes of whitespace, as the age tool does, and
the text form reader skips the blank lines. The README's age decrypt
section says so.

Judgement call: that first line with spaces in front of it on the same
line is still refused, as age refuses it.

Model: opus-5-5
Co-authored-by: clawbot <sneak+clawbot@sneak.cloud>
2026-10-14 22:35:29 +02:00
clawbot 5582c02edf Say why a mnemonic is refused (closes #76)
check / check (push) Canceled after 0s
Every way a mnemonic could be invalid was reported as a checksum
failure, including an empty one. It is now refused as empty, as having
a word count other than 12, 15, 18, 21 or 24, as having a word that is
not on the BIP-39 word list, or as failing the checksum. A word not on
the list is named by its position, never by the word itself.

Judgement call: words are not lower-cased, so a capitalised word is
reported as not on the word list.

Model: opus-5-5
Co-authored-by: clawbot <sneak+clawbot@sneak.cloud>
2026-10-14 22:05:37 +02:00
clawbot 44cb5215b0 Turn IdentitiesOnly off for ssh to (closes #74)
check / check (push) Canceled after 0s
ssh to now gives ssh -o IdentitiesOnly=no before the host, next to
-o IdentityAgent. With IdentitiesOnly yes in the user's ssh
configuration, ssh listed the agent's key but never offered it, and
the login failed with Permission denied. An option on the command
line wins over the configuration, and the tool's agent holds only the
derived key, so turning the option off adds no other key. A test
against the stand-in ssh requires the option before the host, and the
README's ssh to section names both options.

Judgement call: a user's own -o IdentitiesOnly=yes after the host is
now overridden.

Model: opus-5-5
Co-authored-by: clawbot <sneak+clawbot@sneak.cloud>
2026-10-14 21:12:58 +02:00
clawbot b02f502928 Keep the mnemonic variables from the mnemonic command (closes #80)
check / check (push) Canceled after 0s
The mnemonic command ran with the tool's whole environment, so a
mnemonic set in KEYFUNC_MNEMONIC reached it, although the command is
there to supply one of its own. It now gets the environment ssh and
sftp already get, with KEYFUNC_MNEMONIC and KEYFUNC_MNEMONIC_COMMAND
removed. The function that builds that environment moves from the ssh
command group into internal/mnemonic, beside the two variable names,
so all three programs use the one copy. The README says so.

A mnemonic command that runs keyfunc itself no longer finds the main
mnemonic in either variable.

Model: opus-5-5
Co-authored-by: clawbot <sneak+clawbot@sneak.cloud>
2026-10-14 20:48:21 +02:00
clawbot 45463fa35b Require secret at the commit that drops go-bip39 (closes #70)
check / check (push) Successful in 5m8s
sneak/secret now carries its own copy of go-bip39
(sneak/secret#130), so requiring it at that
commit, ef0ae90, lets go mod tidy drop go-bip39 from go.sum. Earlier,
secret renamed its module to sneak.berlin/go/secret
(sneak/secret#43), so the requirement, the
two imports of its bip85 package and the README sentence naming that
package move to the new path. The bip85 functions keyfunc calls are
unchanged, and no other requirement moves.

Model: opus-5-5
Co-authored-by: clawbot <sneak+clawbot@sneak.cloud>
2026-10-07 13:43:37 +02:00
clawbot ccdc576cd3 Copy go-bip39 into internal/bip39 (closes #42)
check / check (push) Successful in 4m30s
go-bip39's repository no longer exists, so keyfunc now carries the
part of v1.1.0 it uses, with the upstream LICENSE beside it, and
imports it from internal/bip39. Upstream's tests and test vectors for
the kept code come along unchanged; where they called a removed
function, crypto/rand stands in for NewEntropy and EntropyFromMnemonic
for MnemonicToByteArray.

Changes beyond the trimming are what the linter asked for: the
package-level variables moved into the functions that use them, three
error strings were lower-cased, and the unknown-word error now wraps
ErrInvalidMnemonic.

go.mod no longer requires go-bip39. go mod tidy keeps its two go.sum
lines, because a test in sneak/secret's bip85 package imports it, and
drops six lines that only go-bip39's own requirements needed.

Model: opus-5-5
Co-authored-by: clawbot <sneak+clawbot@sneak.cloud>
2026-10-06 03:27:15 +02:00
clawbot e82c91d27c package.json carries the license field, as the template does (closes #65)
check / check (push) Failing after 4s
package.json now carries "license": "MIT", as the sneak/prompts template does since 2026-10-04, so yarn install in script/bootstrap no longer warns about a missing license field on every image build.

Model: opus-5-5
Co-authored-by: clawbot <sneak+clawbot@sneak.cloud>
2026-10-04 20:59:05 +02:00
clawbot 56e20b66e4 ssh install refuses stray arguments before -- and a symlinked authorized_keys (closes #61)
check / check (push) Failing after 3s
ssh install now takes the host alone before --: any other word there, or a second argument without --, is refused before the mnemonic is read or sftp runs, so keyfunc ssh install alice@host frank@host no longer installs the key for frank@host. The first listing of ~/.ssh is now ls -n, which shows the file type, so a symlinked authorized_keys is refused before any upload instead of being replaced by a regular file; the README says so.

Judgement calls: install -- host is refused; a symlinked authorized_keys is refused even when its target already holds the key.

Model: opus-5-5
Co-authored-by: clawbot <sneak+clawbot@sneak.cloud>
2026-10-04 18:25:45 +02:00
clawbot dad29597bd ssh install ends on a signal while sftp's ssh is still connecting (closes #57)
check / check (push) Failing after 1s
A signal during ssh install now sends sftp a SIGTERM instead of killing it, as ssh to already does for ssh, so sftp stops the ssh it started. The sftp command also has a WaitDelay of a quarter second, so a child that still holds sftp's output cannot keep the tool waiting on a host that does not answer: it ends with status 1 and removes its working directory. The test's sftp stand-in now leaves such a child.

Judgement call: exec.ErrWaitDelay counts as success, so a run that used ControlPersist does not report a failure for a key it added.

Model: opus-5-5
Co-authored-by: clawbot <sneak+clawbot@sneak.cloud>
2026-10-04 14:25:47 +02:00
clawbot d4fbcbc83d README child-mnemonic vector and host-key note; ssh install refuses a ~/.ssh it cannot enter (closes #51)
check / check (push) Successful in 2m4s
The README now gives the child mnemonic keyfunc prints for the abandon ... about test mnemonic at index 0, checked by the README vectors test; the BIP-85 specification vector stays, marked as starting from a master key keyfunc cannot take. It also says ssh install needs the host key in known_hosts already, and how to get round that. ssh install now also lists ~/.ssh/. on its first connection and refuses, before any upload, a ~/.ssh it can read but not enter, which sftp shows as empty; a file where ~/.ssh belongs is refused the same way.

Model: opus-5-5
Co-authored-by: clawbot <sneak+clawbot@sneak.cloud>
2026-10-04 07:25:49 +02:00