check / check (push) Successful in 3m41s
What is on `next`, reviewed. - go-bip39 is gone from `go.mod` and `go.sum`: keyfunc now requires `sneak/secret` at `ef0ae90`, the commit that gives `secret` its own copy (sneak/secret#130). No derived key, mnemonic or test vector changes. To know before merging: - `secret`'s module is now `sneak.berlin/go/secret` (sneak/secret#43), so keyfunc's requirement, its two imports of `secret`'s `bip85` package and one README sentence use that path. The Go module proxy serves that path, so `go install` keeps working. Model: opus-5-5 Reviewed-on: #72 Co-authored-by: clawbot <sneak+clawbot@sneak.cloud>
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"
|
|
|
|
"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")
|
|
|
|
// 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
|
|
}
|