Skip to content

Commit

Permalink
Improve BIP39 seed generation for better space handling
Browse files Browse the repository at this point in the history
  • Loading branch information
mikera committed Jan 5, 2024
1 parent 3d217e3 commit 846732e
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 1 deletion.
15 changes: 14 additions & 1 deletion convex-core/src/main/java/convex/core/crypto/BIP39.java
Original file line number Diff line number Diff line change
Expand Up @@ -225,20 +225,33 @@ public static Blob getSeed(List<String> words, String passphrase) throws NoSuchA
joined=Normalizer.normalize(joined, Normalizer.Form.NFKD);
char[] pass= joined.toCharArray();

return getSeedInternal(pass,passphrase);
}

public static Blob getSeed(String mnemonic, String passphrase) throws NoSuchAlgorithmException, InvalidKeySpecException {
mnemonic=mnemonic.trim().replaceAll("\\s+"," ");
mnemonic=Normalizer.normalize(mnemonic, Normalizer.Form.NFKD);
char[] normalisedMnemonic= mnemonic.toCharArray();
return getSeedInternal(normalisedMnemonic,passphrase);
}

private static Blob getSeedInternal(char[] normalisedMnemonic, String passphrase) throws NoSuchAlgorithmException, InvalidKeySpecException {
// Normalise passphrase and convert to byte array
passphrase=Normalizer.normalize(passphrase, Normalizer.Form.NFKD);
byte[] salt = ("mnemonic"+passphrase).getBytes(StandardCharsets.UTF_8);

// Generate seed
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
KeySpec keyspec = new PBEKeySpec(pass, salt, 2048, SEED_LENGTH * 8);
KeySpec keyspec = new PBEKeySpec(normalisedMnemonic, salt, 2048, SEED_LENGTH * 8);
Key key = factory.generateSecret(keyspec);

// Wrap result as Blob
byte[] bs = key.getEncoded();
return Blob.wrap(bs);
}



public static String createSecureRandom() {
return createSecureRandom(12);
}
Expand Down
18 changes: 18 additions & 0 deletions convex-core/src/test/java/convex/core/crypto/BIP39Test.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package convex.core.crypto;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;

import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
Expand All @@ -20,4 +21,21 @@ public void testSeed() throws NoSuchAlgorithmException, InvalidKeySpecException
String exSeed="8212cc694344bbc4ae70505948c58194c16cd10599b2e93f0f7f638aaa108009a5707f9274fc6bdeb23bf30783d0c2c7bb556a7aa7b9064dab6df9b8c469e39c";
assertEquals(exSeed,BIP39.getSeed(tw1,"").toHexString());
}

/**
* Test vector from https://iancoleman.io/bip39/
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
*/
@Test
public void testExample15() throws NoSuchAlgorithmException, InvalidKeySpecException {
String s1="slush blind shaft return gentle isolate notice busy silent toast joy again almost perfect century";
List<String> tw1=List.of(s1.split(" "));
String exSeed="8ac1d802490b34488eb265d72b3de8aa4cbe4ad0c674ccc083463a3cb9466ab11933f6251aec5b6b2260442435bd2f5257aa3fc219745f642295d8b6e401fe3f";
assertEquals(exSeed,BIP39.getSeed(tw1,"").toHexString());

String s2=s1.replaceAll(" " , " ");
assertNotEquals(s1,s2);
assertEquals(exSeed,BIP39.getSeed(s2,"").toHexString());
}
}

0 comments on commit 846732e

Please sign in to comment.