diff --git a/mnemonic/helpers.go b/mnemonic/helpers.go new file mode 100644 index 00000000..6cd7bba2 --- /dev/null +++ b/mnemonic/helpers.go @@ -0,0 +1,44 @@ +package mnemonic + +import ( + "golang.org/x/crypto/ed25519" + + "github.com/algorand/go-algorand-sdk/types" +) + +// FromPrivateKey is a helper that converts an ed25519 private key to a +// human-readable mnemonic +func FromPrivateKey(sk ed25519.PrivateKey) (string, error) { + seed := sk.Seed() + return FromKey(seed) +} + +// ToPrivateKey is a helper that converts a mnemonic directly to an ed25519 +// private key +func ToPrivateKey(mnemonic string) (sk ed25519.PrivateKey, err error) { + seedBytes, err := ToKey(mnemonic) + if err != nil { + return + } + return ed25519.NewKeyFromSeed(seedBytes), nil +} + +// FromMasterDerivationKey is a helper that converts an MDK to a human-readable +// mnemonic +func FromMasterDerivationKey(mdk types.MasterDerivationKey) (string, error) { + return FromKey(mdk[:]) +} + +// ToMasterDerivationKey is a helper that converts a mnemonic directly to a +// master derivation key +func ToMasterDerivationKey(mnemonic string) (mdk types.MasterDerivationKey, err error) { + mdkBytes, err := ToKey(mnemonic) + if err != nil { + return + } + if len(mdkBytes) != len(mdk) { + panic("recovered mdk is wrong length") + } + copy(mdk[:], mdkBytes) + return +} diff --git a/mnemonic/mnemonic_test.go b/mnemonic/mnemonic_test.go index 700f97f8..1160b01f 100644 --- a/mnemonic/mnemonic_test.go +++ b/mnemonic/mnemonic_test.go @@ -6,6 +6,9 @@ import ( "testing" "github.com/stretchr/testify/require" + + "github.com/algorand/go-algorand-sdk/crypto" + "github.com/algorand/go-algorand-sdk/types" ) func TestGenerateAndRecovery(t *testing.T) { @@ -21,6 +24,31 @@ func TestGenerateAndRecovery(t *testing.T) { require.NoError(t, err) require.Equal(t, recovered, key) } + + var mdk types.MasterDerivationKey + for i := 0; i < 1000; i++ { + // Generate a mdk + _, err := rand.Read(key) + require.NoError(t, err) + copy(mdk[:], key) + // Go from mdk -> mnemonic + m, err := FromMasterDerivationKey(mdk) + // Go from mnemonic -> mdk + recovered, err := ToMasterDerivationKey(m) + require.NoError(t, err) + require.Equal(t, recovered, mdk) + } + + for i := 0; i < 1000; i++ { + // Generate a private key + acct := crypto.GenerateAccount() + // Go from sk -> mnemonic + m, err := FromPrivateKey(acct.PrivateKey) + // Go from mnemonic -> sk + recovered, err := ToPrivateKey(m) + require.NoError(t, err) + require.Equal(t, recovered, acct.PrivateKey) + } } func TestZeroVector(t *testing.T) {