All checks were successful
check / check (push) Successful in 4s
keyfunc mnemonic derives a 12, 18 or 24 word child mnemonic through BIP-85's own mnemonic application, with the specification's test vectors as tests. One review round, passed with no findings; the reviewer reproduced the vectors from an implementation written from the specification alone. Model: opus-5 (implementation and review); fable-5-1 (landing)
64 lines
1.7 KiB
Go
64 lines
1.7 KiB
Go
// Package childmnemonic derives a mnemonic from another mnemonic.
|
|
package childmnemonic
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"git.eeqj.de/sneak/keyfunc/internal/derive"
|
|
"git.eeqj.de/sneak/secret/pkg/bip85"
|
|
"github.com/btcsuite/btcd/btcutil/hdkeychain"
|
|
bip39 "github.com/tyler-smith/go-bip39"
|
|
)
|
|
|
|
// 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")
|
|
|
|
// 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) {
|
|
switch words {
|
|
case twelve, eighteen, twentyFour:
|
|
default:
|
|
return "", fmt.Errorf("%w, not %d", ErrWordCount, words)
|
|
}
|
|
|
|
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
|
|
}
|