From 82c8d614762c3e4bb0abc14148a1fba1ca3182e5 Mon Sep 17 00:00:00 2001 From: Tor Brede Vekterli Date: Wed, 19 Oct 2022 12:40:34 +0200 Subject: Add X25519 private to public key extraction and use for HPKE opening Avoids the need to pass the full key pair when opening a sealed piece of ciphertext, since we can just extract the public key on-demand. Uses BouncyCastle X25519 utils under the hood. --- .../src/test/java/com/yahoo/security/HpkeTest.java | 27 ++++++++++++++-------- .../test/java/com/yahoo/security/KeyUtilsTest.java | 13 +++++++++++ 2 files changed, 31 insertions(+), 9 deletions(-) (limited to 'security-utils/src/test/java/com') diff --git a/security-utils/src/test/java/com/yahoo/security/HpkeTest.java b/security-utils/src/test/java/com/yahoo/security/HpkeTest.java index 24944759c5c..4455eade7cd 100644 --- a/security-utils/src/test/java/com/yahoo/security/HpkeTest.java +++ b/security-utils/src/test/java/com/yahoo/security/HpkeTest.java @@ -9,6 +9,7 @@ import com.yahoo.security.hpke.Kem; import org.junit.jupiter.api.Test; import java.security.KeyPair; +import java.security.interfaces.XECPrivateKey; import java.security.interfaces.XECPublicKey; import static com.yahoo.security.ArrayUtils.hex; @@ -35,6 +36,14 @@ public class HpkeTest { return new KeyPair(pub, priv); } + private static XECPublicKey pk(KeyPair kp) { + return (XECPublicKey) kp.getPublic(); + } + + private static XECPrivateKey sk(KeyPair kp) { + return (XECPrivateKey) kp.getPrivate(); + } + /** * https://www.rfc-editor.org/rfc/rfc9180.html test vector * @@ -55,7 +64,7 @@ public class HpkeTest { var ciphersuite = Ciphersuite.of(kem, Kdf.hkdfSha256(), Aead.aesGcm128()); var hpke = Hpke.of(ciphersuite); - var s = hpke.sealBase((XECPublicKey) kpR.getPublic(), info, aad, pt); + var s = hpke.sealBase(pk(kpR), info, aad, pt); // The "enc" output is the ephemeral public key var expectedEnc = "37fda3567bdbd628e88668c3c8d7e97d1d1253b6d4ea6d44c150f741f1bf4431"; @@ -65,7 +74,7 @@ public class HpkeTest { "6d8770ac83d07bea87e13c512a"; assertEquals(expectedCiphertext, hex(s.ciphertext())); - byte[] openedPt = hpke.openBase(s.enc(), kpR, info, aad, s.ciphertext()); + byte[] openedPt = hpke.openBase(s.enc(), sk(kpR), info, aad, s.ciphertext()); assertEquals(hex(pt), hex(openedPt)); } @@ -78,12 +87,12 @@ public class HpkeTest { var hpke = Hpke.of(Ciphersuite.defaultSuite()); - var s1 = hpke.sealBase((XECPublicKey) kpR.getPublic(), info, aad, pt); - byte[] openedPt = hpke.openBase(s1.enc(), kpR, info, aad, s1.ciphertext()); + var s1 = hpke.sealBase(pk(kpR), info, aad, pt); + byte[] openedPt = hpke.openBase(s1.enc(), sk(kpR), info, aad, s1.ciphertext()); assertEquals(hex(pt), hex(openedPt)); - var s2 = hpke.sealBase((XECPublicKey) kpR.getPublic(), info, aad, pt); - openedPt = hpke.openBase(s2.enc(), kpR, info, aad, s2.ciphertext()); + var s2 = hpke.sealBase(pk(kpR), info, aad, pt); + openedPt = hpke.openBase(s2.enc(), sk(kpR), info, aad, s2.ciphertext()); assertEquals(hex(pt), hex(openedPt)); assertNotEquals(hex(s1.enc()), hex(s2.enc())); // This is the ephemeral public key @@ -97,13 +106,13 @@ public class HpkeTest { var kpR = receiverRrfc9180TestVectorKeyPair(); var hpke = Hpke.of(Ciphersuite.defaultSuite()); - var s = hpke.sealBase((XECPublicKey) kpR.getPublic(), info, aad, pt); + var s = hpke.sealBase(pk(kpR), info, aad, pt); byte[] badInfo = toUtf8Bytes("lesser info"); // TODO better exception classes! Triggers AEAD auth tag mismatch behind the scenes - assertThrows(RuntimeException.class, () -> hpke.openBase(s.enc(), kpR, badInfo, aad, s.ciphertext())); + assertThrows(RuntimeException.class, () -> hpke.openBase(s.enc(), sk(kpR), badInfo, aad, s.ciphertext())); byte[] badAad = toUtf8Bytes("non-groovy AAD"); - assertThrows(RuntimeException.class, () -> hpke.openBase(s.enc(), kpR, info, badAad, s.ciphertext())); + assertThrows(RuntimeException.class, () -> hpke.openBase(s.enc(), sk(kpR), info, badAad, s.ciphertext())); } } diff --git a/security-utils/src/test/java/com/yahoo/security/KeyUtilsTest.java b/security-utils/src/test/java/com/yahoo/security/KeyUtilsTest.java index fbf27b67f4b..97fd8ce9e41 100644 --- a/security-utils/src/test/java/com/yahoo/security/KeyUtilsTest.java +++ b/security-utils/src/test/java/com/yahoo/security/KeyUtilsTest.java @@ -170,4 +170,17 @@ public class KeyUtilsTest { assertEquals(pubHex, xecHexFromPub(pub2)); } + @Test + void can_extract_public_key_from_x25519_private_key() { + var priv = xecPrivFromHex("77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a"); + var expectedPubHex = "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"; + var pub = KeyUtils.extractX25519PublicKey(priv); + assertEquals(expectedPubHex, xecHexFromPub(pub)); + + priv = xecPrivFromHex("5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb"); + expectedPubHex = "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f"; + pub = KeyUtils.extractX25519PublicKey(priv); + assertEquals(expectedPubHex, xecHexFromPub(pub)); + } + } -- cgit v1.2.3