forked from Qortal/qortal
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.
This commit is contained in:
parent
1b4369e5e8
commit
f3c588d90f
@ -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);
|
||||
|
||||
|
@ -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
Normal file
22
src/test/resources/ed25519-to-x25519.html
Normal file
@ -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…
Reference in New Issue
Block a user