diff --git a/convex-core/src/main/java/convex/core/crypto/BIP39.java b/convex-core/src/main/java/convex/core/crypto/BIP39.java index 1b737b60a..5e2f72f0b 100644 --- a/convex-core/src/main/java/convex/core/crypto/BIP39.java +++ b/convex-core/src/main/java/convex/core/crypto/BIP39.java @@ -273,14 +273,20 @@ public static Blob seedToEd25519Seed(Blob seed) { } /** - * Tests if the string is a valid mnemonic phrase, returns null if no problem + * Tests if the string is a valid BIP39 mnemonic phrase, returns null if no problem * @param s String to be tested as a mnemonic phrase * @return String containing reason that mnemonic is not valid, or null if OK */ public static String checkMnemonic(String s) { List words=getWords(s); if (words.size() createWords(SecureRandom r, int n) { return createWords(bs,n); } - public static List createWords(byte[] entropy, int n) { + public static List createWordsAddingChecksum(byte[] entropy, int n) { int CS=n/3; // number of checksum bits int ENT=CS*32; Hash checkHash=Hashing.sha256(entropy); int checkSum=Utils.extractBits(checkHash.getBytes(), CS, 256-CS); // BIP39 checksum - int blen=((CS+ENT)/8)+1; // enough space for entropy plus checksum + int blen=((CS+ENT+7)/8); // enough space for entropy plus checksum byte[] bs=new byte[blen]; System.arraycopy(entropy, 0, bs, 0, ENT/8); Utils.setBits(bs, CS, (blen*8)-(ENT+CS),checkSum); + return createWords(bs,n); + } + + public static List createWords(byte[] material, int n) { + int mbits=material.length*8; ArrayList al=new ArrayList<>(n); for (int i=0; i words=getWords(mnemonic); + int n=words.size(); + if ((n24)) return null; + + int CS=n/3; + if ((CS*3!=n)) return null; // must be a multiple of 3 for valid BIP39 + int ENT=CS*32; + + int blen=((CS+ENT+7)/8); // enough space for entropy plus checksum + byte[] bs=new byte[blen]; + + for (int i=0; i words=BIP39.getWords(m); + int n=words.size(); try { Blob seed=BIP39.getSeed(words, PP); assertEquals(BIP39.SEED_LENGTH,seed.count()); @@ -131,16 +130,19 @@ private void doValidStringTest(String m) { // Wrong passphrase => different seed assertNotEquals(seed,BIP39.getSeed(words, "badpass")); - // with extra whitespace is OK - assertEquals(seed,BIP39.getSeed(" \t "+m, PP)); - AKeyPair kp=BIP39.seedToKeyPair(seed); assertNotNull(kp); } catch (Exception e) { - fail("Enexpected Exception "+e); + fail("Unexpected Exception "+e); } + // Tests for round trips to entropy + byte[] bs=BIP39.mnemonicToBytes(m); + List rwords=BIP39.createWords(bs, n); + String rm=BIP39.mnemonic(rwords); + + assertEquals(m,rm); } @Test diff --git a/convex-gui/src/main/java/convex/gui/keys/KeyGenPanel.java b/convex-gui/src/main/java/convex/gui/keys/KeyGenPanel.java index ef05d6b17..4f9accd55 100644 --- a/convex-gui/src/main/java/convex/gui/keys/KeyGenPanel.java +++ b/convex-gui/src/main/java/convex/gui/keys/KeyGenPanel.java @@ -87,7 +87,6 @@ private void updatePass() { private void generateBIP39Seed() { String s = mnemonicArea.getText(); String p = new String(passArea.getPassword()); - List words=BIP39.getWords(s); String warn=checkWarnings(s,p); @@ -100,7 +99,7 @@ private void generateBIP39Seed() { } try { - Blob bipSeed=BIP39.getSeed(words,p); + Blob bipSeed=BIP39.getSeed(s, p); seedArea.setText(bipSeed.toHexString()); deriveSeed(); } catch (Exception ex) {