// Package derive turns a mnemonic into the bytes a key is made from. package derive import ( "fmt" "git.eeqj.de/sneak/secret/pkg/bip85" "github.com/btcsuite/btcd/btcutil/hdkeychain" "github.com/btcsuite/btcd/chaincfg" bip39 "github.com/tyler-smith/go-bip39" ) const ( // purpose is the number BIP-85 reserves for itself. purpose = 83696968 // Size is how many bytes every key type is given. Size = 32 ) // Path returns the derivation path for an application number and a key // index. func Path(application, index uint32) string { return fmt.Sprintf("m/%d'/%d'/%d'", purpose, application, index) } // Bytes returns the bytes for an application number and a key index. // The mnemonic becomes a seed with an empty passphrase, the seed // becomes a master key, the master key gives BIP-85 entropy at the // path, and the entropy seeds the generator the bytes are read from. func Bytes(words string, application, index uint32) ([]byte, error) { seed := bip39.NewSeed(words, "") master, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams) if err != nil { return nil, fmt.Errorf("making the master key: %w", err) } entropy, err := bip85.DeriveBIP85Entropy(master, Path(application, index)) if err != nil { return nil, fmt.Errorf("deriving entropy: %w", err) } out := make([]byte, Size) _, err = bip85.NewBIP85DRNG(entropy).Read(out) if err != nil { return nil, fmt.Errorf("reading derived bytes: %w", err) } return out, nil }