Derive the vault key from the mnemonic's words however they are spaced (closes #135) #160

Merged
clawbot merged 1 commits from mnemonic-whitespace into next 2026-10-13 01:09:37 +02:00
Collaborator

Fixes #135.

What was wrong: the vault's long-term key was derived from the mnemonic text exactly as typed. init and vault create accept a mnemonic with a double space, a tab or a trailing newline, because the check splits the words on any whitespace, but the key came from the raw text. Such a vault did not open with the same words typed normally, and its key matched no other BIP39 tool.

What the fix does: agehd.DeriveEntropy joins the words with single spaces and puts them in Unicode NFKD, as BIP39 defines the seed's input, before hashing them. init, vault create, vault import, unlocker add and every unlock derive the key through it, so none of them changed. The new test in pkg/agehd derives an identity from the words with a double space and a trailing space, and from the words split by tabs and newlines, and requires the identity of the single-spaced words; it failed before the change.

Worth knowing:

  • golang.org/x/text moves from indirect to direct in go.mod; go.sum already had it.
  • NFKD changes nothing for the English word list, the only one secret accepts. It is there because BIP39 and the issue define the seed's input that way.

Judgement call: internal/bip39's NewSeed still hashes its input as given, as upstream does; the normalising is in agehd.

Model: opus-5-5

Fixes https://git.eeqj.de/sneak/secret/issues/135. **What was wrong:** the vault's long-term key was derived from the mnemonic text exactly as typed. `init` and `vault create` accept a mnemonic with a double space, a tab or a trailing newline, because the check splits the words on any whitespace, but the key came from the raw text. Such a vault did not open with the same words typed normally, and its key matched no other BIP39 tool. **What the fix does:** `agehd.DeriveEntropy` joins the words with single spaces and puts them in Unicode NFKD, as BIP39 defines the seed's input, before hashing them. `init`, `vault create`, `vault import`, `unlocker add` and every unlock derive the key through it, so none of them changed. The new test in `pkg/agehd` derives an identity from the words with a double space and a trailing space, and from the words split by tabs and newlines, and requires the identity of the single-spaced words; it failed before the change. Worth knowing: - `golang.org/x/text` moves from indirect to direct in `go.mod`; `go.sum` already had it. - NFKD changes nothing for the English word list, the only one `secret` accepts. It is there because BIP39 and the issue define the seed's input that way. Judgement call: `internal/bip39`'s `NewSeed` still hashes its input as given, as upstream does; the normalising is in `agehd`. Model: opus-5-5
clawbot added the needs-review label 2026-10-13 00:56:18 +02:00
clawbot self-assigned this 2026-10-13 00:56:18 +02:00
clawbot added 1 commit 2026-10-13 00:56:19 +02:00
The long-term key was derived from the mnemonic text exactly as typed,
so a double space, a tab or a trailing newline gave a different key,
and a vault made that way did not open with the same words typed
normally. agehd.DeriveEntropy, which init, vault create, vault import,
unlocker add and every unlock go through, now joins the words with
single spaces and puts them in Unicode NFKD, as BIP39 defines the
seed's input, before hashing them. golang.org/x/text, already an
indirect dependency, becomes a direct one for the NFKD step.

Judgement call: internal/bip39's NewSeed keeps hashing its input as
given, as upstream does; the normalising is in agehd.

Model: opus-5-5
Author
Collaborator

Passes review: a mnemonic typed with extra spaces, tabs or line breaks now gives the same vault key as its single-spaced words everywhere the key is derived, as #135 defines.

Model: opus-5-5

Passes review: a mnemonic typed with extra spaces, tabs or line breaks now gives the same vault key as its single-spaced words everywhere the key is derived, as https://git.eeqj.de/sneak/secret/issues/135 defines. Model: opus-5-5
clawbot merged commit fd6c5df1a8 into next 2026-10-13 01:09:37 +02:00
clawbot deleted branch mnemonic-whitespace 2026-10-13 01:09:38 +02:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/secret#160