From 484361c034676743a999da8ebe3bcb4e042f100b Mon Sep 17 00:00:00 2001 From: Jim McDonald Date: Thu, 18 May 2023 23:56:14 +0100 Subject: [PATCH] Support 12- and 18-word mnemonics with passphrases. Allow single-world (no whitespace) passphrases for 12- and 18-word mnemonics. Fixes #87 --- CHANGELOG.md | 1 + util/mnemonic.go | 14 ++++++++++++-- util/mnemonic_test.go | 27 ++++++++++++++++++++++++++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 929c0ae..cff9187 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ dev: - initial support for deneb - add "--generate-keystore" option for "account derive" - update "validator exit" command to be able to generate multiple exits + - support for 12-word and 18-word mnemonics with single-word (no whitespace) passphrases 1.30.0: - add "chain spec" command diff --git a/util/mnemonic.go b/util/mnemonic.go index 4f49e32..3433871 100644 --- a/util/mnemonic.go +++ b/util/mnemonic.go @@ -40,13 +40,23 @@ var mnemonicWordLists = [][]string{ // SeedFromMnemonic creates a seed from a mnemonic. func SeedFromMnemonic(mnemonic string) ([]byte, error) { - // If there are more than 24 words we treat the additional characters as the passphrase. + // Handle situations where there may be a passphrase with the mnemonic. mnemonicParts := strings.Split(mnemonic, " ") mnemonicPassphrase := "" - if len(mnemonicParts) > 24 { + switch { + case len(mnemonicParts) == 13: + // Assume that passphrase is a single word here. + mnemonic = strings.Join(mnemonicParts[:12], " ") + mnemonicPassphrase = mnemonicParts[12] + case len(mnemonicParts) == 19: + // Assume that passphrase is a single word here. + mnemonic = strings.Join(mnemonicParts[:18], " ") + mnemonicPassphrase = mnemonicParts[18] + case len(mnemonicParts) > 24: mnemonic = strings.Join(mnemonicParts[:24], " ") mnemonicPassphrase = strings.Join(mnemonicParts[24:], " ") } + // Normalise the input. mnemonic = string(norm.NFKD.Bytes([]byte(mnemonic))) mnemonicPassphrase = string(norm.NFKD.Bytes([]byte(mnemonicPassphrase))) diff --git a/util/mnemonic_test.go b/util/mnemonic_test.go index 7f2d56d..953ef79 100644 --- a/util/mnemonic_test.go +++ b/util/mnemonic_test.go @@ -42,10 +42,35 @@ func TestSeedFromMnemonic(t *testing.T) { err: "mnemonic is invalid", }, { - name: "Default", + name: "Twelve", + mnemonic: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about", + seed: bytesStr("0x5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4"), + }, + { + name: "TwelvePlusPassphrase", + mnemonic: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about passphrase", + seed: bytesStr("0x4865438d10636e1453b2d3c06444c669b80fb1ae77111f1f91b64278ed4d493465276d2e00f93be2a8e82c2f72555370a4bf31bcf1f9addaf0a31499a3baeeae"), + }, + { + name: "Eighteen", + mnemonic: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent", + seed: bytesStr("0x4975bb3d1faf5308c86a30893ee903a976296609db223fd717e227da5a813a34dc1428b71c84a787fc51f3b9f9dc28e9459f48c08bd9578e9d1b170f2d7ea506"), + }, + { + name: "EighteenPlusPassphrase", + mnemonic: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent passphrase", + seed: bytesStr("0xbea1dd48440f3a8a7c02d0f7977fe03ba1dd409dda1ce971e80adc38f750c51d0959bd15c48cca2649cbcba8160d8a6c4026f2ee22dd387aa9b005041a5b8ea2"), + }, + { + name: "TwentyFour", mnemonic: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art", seed: bytesStr("0x408b285c123836004f4b8842c89324c1f01382450c0d439af345ba7fc49acf705489c6fc77dbd4e3dc1dd8cc6bc9f043db8ada1e243c4a0eafb290d399480840"), }, + { + name: "TwentyFourPlusPassphrase", + mnemonic: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art passphrase", + seed: bytesStr("0x3b9096d658962052e9e778a18e7fddb8f530cbf783f38b26cf3e89fff6bf385728028ea0e906d47c24f88b666d61a59bdb88a7fc11b9e302ae75482c9562c282"), + }, { name: "English", mnemonic: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art",