From f32930be380f499d2f270594c686aef464ef8605 Mon Sep 17 00:00:00 2001 From: Antoine Toulme Date: Fri, 8 Feb 2019 19:28:18 -0800 Subject: [PATCH] Add conversion from signature to box keys --- .../net/consensys/cava/crypto/sodium/Box.java | 75 ++++++++++++++----- .../cava/crypto/sodium/LibSodium.java | 2 +- .../cava/crypto/sodium/Signature.java | 2 +- .../consensys/cava/crypto/sodium/Sodium.java | 2 +- .../consensys/cava/crypto/sodium/BoxTest.java | 12 +++ 5 files changed, 71 insertions(+), 22 deletions(-) diff --git a/crypto/src/main/java/net/consensys/cava/crypto/sodium/Box.java b/crypto/src/main/java/net/consensys/cava/crypto/sodium/Box.java index 55b90318..d4ddf898 100644 --- a/crypto/src/main/java/net/consensys/cava/crypto/sodium/Box.java +++ b/crypto/src/main/java/net/consensys/cava/crypto/sodium/Box.java @@ -119,6 +119,33 @@ public static PublicKey fromBytes(byte[] bytes) { return Sodium.dup(bytes, PublicKey::new); } + /** + * Transforms the Ed25519 signature public key to a Curve25519 public key. See + * https://libsodium.gitbook.io/doc/advanced/ed25519-curve25519 + * + * @param publicKey the signature public key + * @return the public key as a Curve25519 public key + */ + public static PublicKey forSignaturePublicKey(Signature.PublicKey publicKey) { + Pointer publicKeyPtr = null; + try { + int publicKeyLength = PublicKey.length(); + publicKeyPtr = Sodium.malloc(publicKeyLength); + int rc = Sodium.crypto_sign_ed25519_pk_to_curve25519(publicKeyPtr, publicKey.ptr); + if (rc != 0) { + throw new SodiumException("crypto_sign_ed25519_pk_to_curve25519: failed with results " + rc); + } + PublicKey pk = new PublicKey(publicKeyPtr, publicKeyLength); + publicKeyPtr = null; + return pk; + } catch (Throwable e) { + if (publicKeyPtr != null) { + Sodium.sodium_free(publicKeyPtr); + } + throw e; + } + } + /** * Obtain the length of the key in bytes (32). * @@ -226,6 +253,34 @@ public static SecretKey fromBytes(byte[] bytes) { return Sodium.dup(bytes, SecretKey::new); } + /** + * Transforms the Ed25519 secret key to a Curve25519 secret key. See + * https://libsodium.gitbook.io/doc/advanced/ed25519-curve25519 + * + * @param secretKey the signature secret key + * @return the secret key as a Curve25519 secret key + */ + public static SecretKey forSignatureSecretKey(Signature.SecretKey secretKey) { + checkArgument(secretKey.ptr != null, "Signature.SecretKey has been destroyed"); + Pointer secretKeyPtr = null; + try { + int secretKeyLength = SecretKey.length(); + secretKeyPtr = Sodium.malloc(secretKeyLength); + int rc = Sodium.crypto_sign_ed25519_sk_to_curve25519(secretKeyPtr, secretKey.ptr); + if (rc != 0) { + throw new SodiumException("crypto_sign_ed25519_sk_to_curve25519: failed with results " + rc); + } + SecretKey sk = new SecretKey(secretKeyPtr, secretKeyLength); + secretKeyPtr = null; + return sk; + } catch (Throwable e) { + if (secretKeyPtr != null) { + Sodium.sodium_free(secretKeyPtr); + } + throw e; + } + } + /** * Obtain the length of the key in bytes (32). * @@ -485,25 +540,7 @@ public static KeyPair fromSeed(Seed seed) { * @return A {@link KeyPair}. */ public static KeyPair forSignatureKeyPair(Signature.KeyPair keyPair) { - Pointer signatureSecretKeyPtr = keyPair.secretKey().ptr; - checkArgument(signatureSecretKeyPtr != null, "Signature.SecretKey has been destroyed"); - Pointer secretKey = null; - try { - int secretKeyLength = SecretKey.length(); - secretKey = Sodium.malloc(secretKeyLength); - int rc = Sodium.crypto_sign_ed25519_sk_to_curve25519(secretKey, keyPair.secretKey().ptr); - if (rc != 0) { - throw new SodiumException("crypto_sign_ed25519_sk_to_curve25519: failed with results " + rc); - } - SecretKey sk = new SecretKey(secretKey, secretKeyLength); - secretKey = null; - return forSecretKey(sk); - } catch (Throwable e) { - if (secretKey != null) { - Sodium.sodium_free(secretKey); - } - throw e; - } + return forSecretKey(SecretKey.forSignatureSecretKey(keyPair.secretKey())); } /** diff --git a/crypto/src/main/java/net/consensys/cava/crypto/sodium/LibSodium.java b/crypto/src/main/java/net/consensys/cava/crypto/sodium/LibSodium.java index 0ab3290a..ed95fd3c 100644 --- a/crypto/src/main/java/net/consensys/cava/crypto/sodium/LibSodium.java +++ b/crypto/src/main/java/net/consensys/cava/crypto/sodium/LibSodium.java @@ -1856,7 +1856,7 @@ int crypto_sign_ed25519_detached( int crypto_sign_ed25519_seed_keypair(@Out byte[] pk, @Out byte[] sk, @In byte[] seed); // int crypto_sign_ed25519_pk_to_curve25519(unsigned char * curve25519_pk, const unsigned char * ed25519_pk); - int crypto_sign_ed25519_pk_to_curve25519(@Out byte[] curve25519_pk, @In byte[] ed25519_pk); + int crypto_sign_ed25519_pk_to_curve25519(@Out Pointer curve25519_pk, @In Pointer ed25519_pk); // int crypto_sign_ed25519_sk_to_curve25519(unsigned char * curve25519_sk, const unsigned char * ed25519_sk); int crypto_sign_ed25519_sk_to_curve25519(@Out Pointer curve25519_sk, @In Pointer ed25519_sk); diff --git a/crypto/src/main/java/net/consensys/cava/crypto/sodium/Signature.java b/crypto/src/main/java/net/consensys/cava/crypto/sodium/Signature.java index 9d186aa1..49e230d5 100644 --- a/crypto/src/main/java/net/consensys/cava/crypto/sodium/Signature.java +++ b/crypto/src/main/java/net/consensys/cava/crypto/sodium/Signature.java @@ -59,7 +59,7 @@ public final class Signature { * A signing public key. */ public static final class PublicKey { - private final Pointer ptr; + final Pointer ptr; private final int length; private PublicKey(Pointer ptr, int length) { diff --git a/crypto/src/main/java/net/consensys/cava/crypto/sodium/Sodium.java b/crypto/src/main/java/net/consensys/cava/crypto/sodium/Sodium.java index d4b27723..c902061b 100644 --- a/crypto/src/main/java/net/consensys/cava/crypto/sodium/Sodium.java +++ b/crypto/src/main/java/net/consensys/cava/crypto/sodium/Sodium.java @@ -2194,7 +2194,7 @@ static int crypto_sign_ed25519_seed_keypair(byte[] pk, byte[] sk, byte[] seed) { return libSodium().crypto_sign_ed25519_seed_keypair(pk, sk, seed); } - static int crypto_sign_ed25519_pk_to_curve25519(byte[] curve25519_pk, byte[] ed25519_pk) { + static int crypto_sign_ed25519_pk_to_curve25519(Pointer curve25519_pk, Pointer ed25519_pk) { return libSodium().crypto_sign_ed25519_pk_to_curve25519(curve25519_pk, ed25519_pk); } diff --git a/crypto/src/test/java/net/consensys/cava/crypto/sodium/BoxTest.java b/crypto/src/test/java/net/consensys/cava/crypto/sodium/BoxTest.java index 375229a5..a0882ea3 100644 --- a/crypto/src/test/java/net/consensys/cava/crypto/sodium/BoxTest.java +++ b/crypto/src/test/java/net/consensys/cava/crypto/sodium/BoxTest.java @@ -14,6 +14,7 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assumptions.assumeTrue; @@ -179,4 +180,15 @@ void checkBoxKeyPairForSignatureKeyPair() { Box.KeyPair boxKeyPair = Box.KeyPair.forSignatureKeyPair(signKeyPair); assertNotNull(boxKeyPair); } + + @Test + void checkBoxKeysForSignatureKeys() { + Signature.KeyPair keyPair = Signature.KeyPair.random(); + Box.PublicKey boxPubKey = Box.PublicKey.forSignaturePublicKey(keyPair.publicKey()); + Box.SecretKey boxSecretKey = Box.SecretKey.forSignatureSecretKey(keyPair.secretKey()); + assertEquals(boxPubKey, Box.KeyPair.forSecretKey(boxSecretKey).publicKey()); + + Box.KeyPair boxKeyPair = Box.KeyPair.forSignatureKeyPair(keyPair); + assertEquals(boxKeyPair, Box.KeyPair.forSecretKey(boxSecretKey)); + } }