check / check (push) Waiting to run
The key index, --words, the --to recipients and the input file of age encrypt and age decrypt were checked only after the mnemonic had been obtained, so a run that could not succeed still prompted for it or ran the mnemonic command. options.Index now refuses an index above derive.MaxIndex, which covers every command group; the mnemonic command calls the new childmnemonic.CheckWords first; age encrypt reads its recipients with the new agekey.Recipients, and both age commands open their input, before the key is derived. Encrypt now takes the parsed recipients. The README says which checks come first. Model: opus-5-5
74 lines
1.9 KiB
Go
74 lines
1.9 KiB
Go
// Package childmnemonic derives a mnemonic from another mnemonic.
|
|
package childmnemonic
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/btcsuite/btcd/btcutil/hdkeychain"
|
|
"sneak.berlin/go/keyfunc/internal/bip39"
|
|
"sneak.berlin/go/keyfunc/internal/derive"
|
|
"sneak.berlin/go/secret/pkg/bip85"
|
|
)
|
|
|
|
// english is the number BIP-85 gives the English word list.
|
|
const english = 0
|
|
|
|
// The lengths a child mnemonic may have. BIP-85 also allows 15 and 21
|
|
// words; these three are the ones this tool offers.
|
|
const (
|
|
twelve = 12
|
|
eighteen = 18
|
|
twentyFour = 24
|
|
)
|
|
|
|
// DefaultWords is how long a child mnemonic is when the user does not
|
|
// say.
|
|
const DefaultWords = twelve
|
|
|
|
// ErrWordCount is returned for a length this tool does not offer.
|
|
var ErrWordCount = errors.New("a child mnemonic has 12, 18 or 24 words")
|
|
|
|
// CheckWords refuses a length this tool does not offer, so that the
|
|
// command can turn it down before it looks for the mnemonic.
|
|
func CheckWords(words uint32) error {
|
|
switch words {
|
|
case twelve, eighteen, twentyFour:
|
|
return nil
|
|
default:
|
|
return fmt.Errorf("%w, not %d", ErrWordCount, words)
|
|
}
|
|
}
|
|
|
|
// Derive returns the English child mnemonic of that many words at that
|
|
// key index, taken from the master key with BIP-85's own mnemonic
|
|
// application, number 39. The words come straight from the BIP-85
|
|
// entropy, cut to the length the word count needs, rather than from
|
|
// the generator the other key types read their bytes from.
|
|
func Derive(
|
|
master *hdkeychain.ExtendedKey,
|
|
words, index uint32,
|
|
) (string, error) {
|
|
err := CheckWords(words)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
err = derive.CheckIndex(index)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
entropy, err := bip85.DeriveBIP39Entropy(master, english, words, index)
|
|
if err != nil {
|
|
return "", fmt.Errorf("deriving entropy: %w", err)
|
|
}
|
|
|
|
child, err := bip39.NewMnemonic(entropy)
|
|
if err != nil {
|
|
return "", fmt.Errorf("turning the entropy into words: %w", err)
|
|
}
|
|
|
|
return child, nil
|
|
}
|