any-sync/util/crypto/mnemonic.go
2023-03-27 01:34:51 +02:00

91 lines
1.8 KiB
Go

package crypto
import (
"bytes"
"errors"
"github.com/anytypeio/go-slip10"
"github.com/tyler-smith/go-bip39"
)
var (
ErrInvalidWordCount = errors.New("error invalid word count for mnemonic")
ErrInvalidMnemonic = errors.New("error invalid mnemonic")
)
type MnemonicGenerator struct {
mnemonic string
}
func NewMnemonicGenerator() MnemonicGenerator {
return MnemonicGenerator{}
}
type Mnemonic string
func (g *MnemonicGenerator) WithWordCount(wc int) (Mnemonic, error) {
size := 0
switch wc {
case 12:
size = 128
case 15:
size = 160
case 18:
size = 192
case 21:
size = 224
case 24:
size = 256
default:
return "", ErrInvalidWordCount
}
return g.WithWordCount(size)
}
func (g *MnemonicGenerator) WithRandomEntropy(size int) (Mnemonic, error) {
entropy, err := bip39.NewEntropy(size)
if err != nil {
return "", err
}
mnemonic, err := bip39.NewMnemonic(entropy)
if err != nil {
return "", err
}
return Mnemonic(mnemonic), nil
}
func (g *MnemonicGenerator) WithEntropy(b []byte) (Mnemonic, error) {
mnemonic, err := bip39.NewMnemonic(b)
if err != nil {
return "", err
}
return Mnemonic(mnemonic), nil
}
func (m Mnemonic) DeriveEd25519Key(index int) (PrivKey, error) {
seed, err := bip39.NewSeedWithErrorChecking(string(m), "")
if err != nil {
if err == bip39.ErrInvalidMnemonic {
return nil, ErrInvalidMnemonic
}
return nil, err
}
masterKey, err := slip10.DeriveForPath(AnytypeAccountPrefix, seed)
if err != nil {
return nil, err
}
key, err := masterKey.Derive(slip10.FirstHardenedIndex + uint32(index))
if err != nil {
return nil, err
}
reader := bytes.NewReader(key.RawSeed())
privKey, _, err := GenerateEd25519Key(reader)
return privKey, err
}
func (m Mnemonic) Bytes() ([]byte, error) {
return bip39.MnemonicToByteArray(string(m), true)
}