Browse Source

Fix sometimes erroneous Ed25519 public key to X25519 public key conversion.

Added mass (x1000) testing of key conversion and shared secret calculations.

Fix incorrect proxy private key test that has expected result from previous
algorithm.

Added another test HTML/JS file.
pull/67/head
catbref 5 years ago
parent
commit
f3c588d90f
  1. 2
      src/main/java/org/qora/crypto/BouncyCastle25519.java
  2. 47
      src/test/java/org/qora/test/CryptoTests.java
  3. 22
      src/test/resources/ed25519-to-x25519.html

2
src/main/java/org/qora/crypto/BouncyCastle25519.java

@ -71,6 +71,8 @@ public class BouncyCastle25519 {
int[] u = new int[X25519Field.SIZE];
X25519Field.mul(onePlusY, oneMinusYInverted, u);
X25519Field.normalize(u);
byte[] x25519PublicKey = new byte[X25519.SCALAR_SIZE];
X25519Field.encode(u, x25519PublicKey, 0);

47
src/test/java/org/qora/test/CryptoTests.java

@ -64,6 +64,29 @@ public class CryptoTests extends Common {
assertTrue(account.verify(signature, message));
}
@Test
public void testMassEd25519ToX25519() {
// Lots of random tests just in case of leading sign bit issues
SecureRandom random = new SecureRandom();
for (int i = 0; i < 1000; ++i) {
byte[] ed25519PrivateKey = new byte[32];
random.nextBytes(ed25519PrivateKey);
PrivateKeyAccount account = new PrivateKeyAccount(null, ed25519PrivateKey);
byte[] x25519PrivateKey = BouncyCastle25519.toX25519PrivateKey(account.getPrivateKey());
X25519PrivateKeyParameters x25519PrivateKeyParams = new X25519PrivateKeyParameters(x25519PrivateKey, 0);
// Derive X25519 public key from X25519 private key
byte[] x25519PublicKeyFromPrivate = x25519PrivateKeyParams.generatePublicKey().getEncoded();
// Derive X25519 public key from Ed25519 public key
byte[] x25519PublicKeyFromEd25519 = BouncyCastle25519.toX25519PublicKey(account.getPublicKey());
assertEquals(String.format("Public keys do not match, from private key %s", Base58.encode(ed25519PrivateKey)), Base58.encode(x25519PublicKeyFromPrivate), Base58.encode(x25519PublicKeyFromEd25519));
}
}
@Test
public void testBCseed() {
final String privateKey58 = "A9MNsATgQgruBUjxy2rjWY36Yf19uRioKZbiLFT2P7c6";
@ -197,12 +220,34 @@ public class CryptoTests extends Common {
assertEquals("shared secrets do not match", Base58.encode(ourSharedSecret), Base58.encode(theirSharedSecret));
}
@Test
public void testMassRandomBCSharedSecrets() {
// Lots of random shared secret tests just in case of leading sign bit issues
SecureRandom random = new SecureRandom();
for (int i = 0; i < 1000; ++i) {
byte[] ourPrivateKey = new byte[32];
random.nextBytes(ourPrivateKey);
PrivateKeyAccount ourAccount = new PrivateKeyAccount(null, ourPrivateKey);
byte[] theirPrivateKey = new byte[32];
random.nextBytes(theirPrivateKey);
PrivateKeyAccount theirAccount = new PrivateKeyAccount(null, theirPrivateKey);
byte[] ourSharedSecret = calcBCSharedSecret(ourPrivateKey, theirAccount.getPublicKey());
byte[] theirSharedSecret = calcBCSharedSecret(theirPrivateKey, ourAccount.getPublicKey());
assertEquals("#" + i + " shared secrets do not match", Base58.encode(ourSharedSecret), Base58.encode(theirSharedSecret));
}
}
@Test
public void testProxyKeys() {
final byte[] ourPrivateKey = Base58.decode("A9MNsATgQgruBUjxy2rjWY36Yf19uRioKZbiLFT2P7c6");
final byte[] theirPublicKey = Base58.decode("C6wuddsBV3HzRrXUtezE7P5MoRXp5m3mEDokRDGZB6ry");
final String expectedProxyPrivateKey = "CwBXkJRRaGzWRvdE9vewVUbcYNSVrcTpunNWm8zidArZ";
final String expectedProxyPrivateKey = "6KszntmNuXmpUkzLfuttgMPeownctxrnyZUG9rErKJJx";
PrivateKeyAccount mintingAccount = new PrivateKeyAccount(null, ourPrivateKey);
byte[] proxyPrivateKey = mintingAccount.getProxyPrivateKey(theirPublicKey);

22
src/test/resources/ed25519-to-x25519.html

@ -0,0 +1,22 @@
<!doctype html>
<html>
<head>
<script src="Base58.js"></script>
<script src="nacl_factory.js"></script>
<script>
nacl_factory.instantiate(function (nacl) {
var ed25519PrivateKey = Base58.decode('GQjr1enbi7R4tbRYAbrcwWRWjH9avuC3nRhdGB3pR2DF');
var ed25519KeyPair = nacl.crypto_sign_seed_keypair(ed25519PrivateKey);
var x25519KeyPair = nacl.crypto_box_keypair_from_sign_sk(ed25519KeyPair.signSk);
var x25519PublicKeyFromPrivate = x25519KeyPair.boxPk;
console.log("X25519 public key from private: " + Base58.encode(x25519PublicKeyFromPrivate));
var x25519PublicKeyFromEd25519 = nacl.crypto_box_pk_from_sign_pk(ed25519KeyPair.signPk);
console.log("X25519 public key from Ed25519: " + Base58.encode(x25519PublicKeyFromEd25519));
});
</script>
</head>
<body>
</body>
</html>
Loading…
Cancel
Save