diff options
author | Tor Brede Vekterli <vekterli@yahooinc.com> | 2022-10-25 15:07:48 +0200 |
---|---|---|
committer | Tor Brede Vekterli <vekterli@yahooinc.com> | 2022-10-25 15:07:48 +0200 |
commit | 9b883fa23c8be0279c94d8d0b21c6058ee7e6bd0 (patch) | |
tree | d9cea17fcf58c3125d26b9edf19aa536e83bba66 /security-utils | |
parent | 2dc4c6b58004d51af887c49760a98804803ab73f (diff) |
Use JDK17's own hex utilities instead of BouncyCastle's
Diffstat (limited to 'security-utils')
4 files changed, 66 insertions, 73 deletions
diff --git a/security-utils/src/main/java/com/yahoo/security/ArrayUtils.java b/security-utils/src/main/java/com/yahoo/security/ArrayUtils.java index 41f19d5c82c..476b2e27048 100644 --- a/security-utils/src/main/java/com/yahoo/security/ArrayUtils.java +++ b/security-utils/src/main/java/com/yahoo/security/ArrayUtils.java @@ -1,9 +1,8 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.security; -import org.bouncycastle.util.encoders.Hex; - import java.nio.charset.StandardCharsets; +import java.util.HexFormat; /** * A small collection of utils for working on arrays of bytes. @@ -32,11 +31,11 @@ public class ArrayUtils { } public static byte[] unhex(String hexStr) { - return Hex.decode(hexStr); + return HexFormat.of().parseHex(hexStr); } public static String hex(byte[] bytes) { - return Hex.toHexString(bytes); + return HexFormat.of().formatHex(bytes); } public static byte[] toUtf8Bytes(String str) { diff --git a/security-utils/src/test/java/com/yahoo/security/HKDFTest.java b/security-utils/src/test/java/com/yahoo/security/HKDFTest.java index bf000cbf8d2..1cf06ab387c 100644 --- a/security-utils/src/test/java/com/yahoo/security/HKDFTest.java +++ b/security-utils/src/test/java/com/yahoo/security/HKDFTest.java @@ -1,13 +1,14 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.security; -import org.bouncycastle.util.encoders.Hex; import org.junit.jupiter.api.Test; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.List; +import static com.yahoo.security.ArrayUtils.hex; +import static com.yahoo.security.ArrayUtils.unhex; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -23,14 +24,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows; */ public class HKDFTest { - private static byte[] fromHex(String hex) { - return Hex.decode(hex); - } - - private static String toHex(byte[] bytes) { - return Hex.toHexString(bytes); - } - private static byte[] sha256DigestOf(byte[]... buffers) { try { MessageDigest digest = MessageDigest.getInstance("SHA-256"); @@ -63,40 +56,40 @@ public class HKDFTest { */ @Test void rfc_5869_test_vector_case_1() { - var ikm = fromHex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"); - var salt = fromHex("000102030405060708090a0b0c"); - var info = fromHex("f0f1f2f3f4f5f6f7f8f9"); + var ikm = unhex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"); + var salt = unhex("000102030405060708090a0b0c"); + var info = unhex("f0f1f2f3f4f5f6f7f8f9"); var hkdf = HKDF.extractedFrom(salt, ikm); var okm = hkdf.expand(42, info); assertEquals("3cb25f25faacd57a90434f64d0362f2a" + "2d2d0a90cf1a5a4c5db02d56ecc4c5bf" + "34007208d5b887185865", - toHex(okm)); + hex(okm)); } @Test void rfc_5869_test_vector_case_1_block_boundary_edge_cases() { - var ikm = fromHex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"); - var salt = fromHex("000102030405060708090a0b0c"); - var info = fromHex("f0f1f2f3f4f5f6f7f8f9"); + var ikm = unhex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"); + var salt = unhex("000102030405060708090a0b0c"); + var info = unhex("f0f1f2f3f4f5f6f7f8f9"); var hkdf = HKDF.extractedFrom(salt, ikm); var okm = hkdf.expand(31, info); // One less than block size assertEquals("3cb25f25faacd57a90434f64d0362f2a" + "2d2d0a90cf1a5a4c5db02d56ecc4c5", - toHex(okm)); + hex(okm)); okm = hkdf.expand(32, info); // Exactly equal to block size assertEquals("3cb25f25faacd57a90434f64d0362f2a" + "2d2d0a90cf1a5a4c5db02d56ecc4c5bf", - toHex(okm)); + hex(okm)); okm = hkdf.expand(33, info); // One more than block size assertEquals("3cb25f25faacd57a90434f64d0362f2a" + "2d2d0a90cf1a5a4c5db02d56ecc4c5bf" + "34", - toHex(okm)); + hex(okm)); } /* @@ -133,21 +126,21 @@ public class HKDFTest { */ @Test void rfc_5869_test_vector_case_2() { - var ikm = fromHex("000102030405060708090a0b0c0d0e0f" + - "101112131415161718191a1b1c1d1e1f" + - "202122232425262728292a2b2c2d2e2f" + - "303132333435363738393a3b3c3d3e3f" + - "404142434445464748494a4b4c4d4e4f"); - var salt = fromHex("606162636465666768696a6b6c6d6e6f" + - "707172737475767778797a7b7c7d7e7f" + - "808182838485868788898a8b8c8d8e8f" + - "909192939495969798999a9b9c9d9e9f" + - "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"); - var info = fromHex("b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + - "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + - "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + - "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + - "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"); + var ikm = unhex("000102030405060708090a0b0c0d0e0f" + + "101112131415161718191a1b1c1d1e1f" + + "202122232425262728292a2b2c2d2e2f" + + "303132333435363738393a3b3c3d3e3f" + + "404142434445464748494a4b4c4d4e4f"); + var salt = unhex("606162636465666768696a6b6c6d6e6f" + + "707172737475767778797a7b7c7d7e7f" + + "808182838485868788898a8b8c8d8e8f" + + "909192939495969798999a9b9c9d9e9f" + + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"); + var info = unhex("b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"); var hkdf = HKDF.extractedFrom(salt, ikm); var okm = hkdf.expand(82, info); @@ -157,7 +150,7 @@ public class HKDFTest { "da3275600c2f09b8367793a9aca3db71" + "cc30c58179ec3e87c14c01d5c1f3434f" + "1d87", - toHex(okm)); + hex(okm)); } /* @@ -179,7 +172,7 @@ public class HKDFTest { */ @Test void rfc_5869_test_vector_case_3() { - var ikm = fromHex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"); + var ikm = unhex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"); var info = new byte[0]; // We don't allow empty salt to the salted factory function, so this is equivalent. @@ -188,17 +181,17 @@ public class HKDFTest { var expectedOkm = "8da4e775a563c18f715f802a063c5a31" + "b8a11f5c5ee1879ec3454e5f3c738d2d" + "9d201395faa4b61a96c8"; - assertEquals(expectedOkm, toHex(okm)); + assertEquals(expectedOkm, hex(okm)); // expand() without explicit context should return as if an empty context array was passed okm = hkdf.expand(42); - assertEquals(expectedOkm, toHex(okm)); + assertEquals(expectedOkm, hex(okm)); } @Test void requested_key_size_is_bounded_and_checked() { - var ikm = fromHex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"); - var salt = fromHex("000102030405060708090a0b0c"); + var ikm = unhex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"); + var salt = unhex("000102030405060708090a0b0c"); var hkdf = HKDF.extractedFrom(salt, ikm); assertThrows(IllegalArgumentException.class, () -> hkdf.expand(-1)); // Can't request negative output size @@ -210,14 +203,14 @@ public class HKDFTest { @Test void missing_salt_to_salted_factory_function_throws_exception() { - var ikm = fromHex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"); + var ikm = unhex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"); assertThrows(NullPointerException.class, () -> HKDF.extractedFrom(null, ikm)); assertThrows(IllegalArgumentException.class, () -> HKDF.extractedFrom(new byte[0], ikm)); } @Test void ikm_can_not_be_null_or_empty() { - var salt = fromHex("000102030405060708090a0b0c"); + var salt = unhex("000102030405060708090a0b0c"); assertThrows(NullPointerException.class, () -> HKDF.extractedFrom(salt, null)); assertThrows(IllegalArgumentException.class, () -> HKDF.extractedFrom(salt, new byte[0])); assertThrows(NullPointerException.class, () -> HKDF.unsaltedExtractedFrom(null)); @@ -231,9 +224,9 @@ public class HKDFTest { @Test void maximal_output_size() { - var ikm = fromHex("bdd9c30b5fab7f22d859db774779b41cc124daf3ce872f6e80951c0edd8f8214"); - var salt = fromHex("90983ed74912c6173d0f7cf8164b525361b89bda04d085341a057bde9083b5af"); - var info = fromHex("e6483e923d37e4ba"); + var ikm = unhex("bdd9c30b5fab7f22d859db774779b41cc124daf3ce872f6e80951c0edd8f8214"); + var salt = unhex("90983ed74912c6173d0f7cf8164b525361b89bda04d085341a057bde9083b5af"); + var info = unhex("e6483e923d37e4ba"); var hkdf = HKDF.extractedFrom(salt, ikm); assertEquals(8160, HKDF.MAX_OUTPUT_SIZE); @@ -242,44 +235,44 @@ public class HKDFTest { // value of the expected OKM output. It's hashes all the way down! var expectedOkmSha256Digest = "c17ce0403e133570191dd1d2ca46f6b62623d62e4f0def8de23a51d65d40a009"; var okmDigest = sha256DigestOf(okm); - assertEquals(expectedOkmSha256Digest, toHex(okmDigest)); + assertEquals(expectedOkmSha256Digest, hex(okmDigest)); } @Test void output_collision_for_different_salts() { - var ikm = fromHex("5943c65bc33bf05a205b04be8ae0ab2e"); - var info = fromHex("be082f301a03f87787a80fbea88941214d50c42b"); + var ikm = unhex("5943c65bc33bf05a205b04be8ae0ab2e"); + var info = unhex("be082f301a03f87787a80fbea88941214d50c42b"); var hkdf = HKDF.unsaltedExtractedFrom(ikm); var okm = hkdf.expand(32, info); var expectedOkm = "e7f384df2eae32addabd068a758dec84ed7fcfd87a5fcceb37b70c51422d7387"; - assertEquals(expectedOkm, toHex(okm)); + assertEquals(expectedOkm, hex(okm)); - var salt = fromHex("0000000000000000000000000000000000000000000000000000000000000000"); + var salt = unhex("0000000000000000000000000000000000000000000000000000000000000000"); hkdf = HKDF.extractedFrom(salt, ikm); okm = hkdf.expand(32, info); - assertEquals(expectedOkm, toHex(okm)); + assertEquals(expectedOkm, hex(okm)); } @Test void salt_longer_than_block_size_is_equivalent_to_hash_of_the_salt() { - var ikm = fromHex("624a5b59c2be55cbe29ea90c0020a7e8c60f2501"); - var info = fromHex("5447e595250d02165aae3e61fa90313e25509a7b"); + var ikm = unhex("624a5b59c2be55cbe29ea90c0020a7e8c60f2501"); + var info = unhex("5447e595250d02165aae3e61fa90313e25509a7b"); var salts = List.of("c737d7278df1ec7c0a549ce964abd51c3df1d3584d49e77208cd3f9f5bbfb32e", "1a08959149f4b073bcd902c9bc4ed0324c21c95590773afc77037d610b9584806aeeeda8b5" + "d588d0cd79e7c12211b8e394067516ce12946d61111a52042b539353"); var expectedOkm = "d45c3909269f4b5f9de1fb2eeb0593a7cb9175c8835aba37e0ee0c4cb3bd87c4"; for (var salt : salts) { - var hkdf = HKDF.extractedFrom(fromHex(salt), ikm); + var hkdf = HKDF.extractedFrom(unhex(salt), ikm); var okm = hkdf.expand(32, info); - assertEquals(expectedOkm, toHex(okm)); + assertEquals(expectedOkm, hex(okm)); } } @Test void salt_shorter_than_the_block_size_is_padded_with_zeros() { - var ikm = fromHex("5943c65bc33bf05a205b04be8ae0ab2e"); - var info = fromHex("be082f301a03f87787a80fbea88941214d50c42b"); + var ikm = unhex("5943c65bc33bf05a205b04be8ae0ab2e"); + var info = unhex("be082f301a03f87787a80fbea88941214d50c42b"); var expectedOkm = "43e371354001617abb70454751059625ef1a64e0f818469c2f886b27140a0166"; var salts = List.of("e69dcaad55fb0536", "e69dcaad55fb05360000000000000000", @@ -289,9 +282,9 @@ public class HKDFTest { "e69dcaad55fb053600000000000000000000000000000000000000000000000000000000000000000000000000000000", "e69dcaad55fb0536000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); for (var salt : salts) { - var hkdf = HKDF.extractedFrom(fromHex(salt), ikm); + var hkdf = HKDF.extractedFrom(unhex(salt), ikm); var okm = hkdf.expand(32, info); - assertEquals(expectedOkm, toHex(okm), "Failed for salt %s".formatted(salt)); + assertEquals(expectedOkm, hex(okm), "Failed for salt %s".formatted(salt)); } } 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 97fd8ce9e41..dc6078c58b7 100644 --- a/security-utils/src/test/java/com/yahoo/security/KeyUtilsTest.java +++ b/security-utils/src/test/java/com/yahoo/security/KeyUtilsTest.java @@ -1,7 +1,6 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.security; -import org.bouncycastle.util.encoders.Hex; import org.junit.jupiter.api.Test; import java.security.KeyPair; @@ -10,6 +9,8 @@ import java.security.PublicKey; import java.security.interfaces.XECPrivateKey; import java.security.interfaces.XECPublicKey; +import static com.yahoo.security.ArrayUtils.hex; +import static com.yahoo.security.ArrayUtils.unhex; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -87,19 +88,19 @@ public class KeyUtilsTest { } private static XECPrivateKey xecPrivFromHex(String hex) { - return KeyUtils.fromRawX25519PrivateKey(Hex.decode(hex)); + return KeyUtils.fromRawX25519PrivateKey(unhex(hex)); } private static String xecHexFromPriv(XECPrivateKey privateKey) { - return Hex.toHexString(KeyUtils.toRawX25519PrivateKeyBytes(privateKey)); + return hex(KeyUtils.toRawX25519PrivateKeyBytes(privateKey)); } private static XECPublicKey xecPubFromHex(String hex) { - return KeyUtils.fromRawX25519PublicKey(Hex.decode(hex)); + return KeyUtils.fromRawX25519PublicKey(unhex(hex)); } private static String xecHexFromPub(XECPublicKey publicKey) { - return Hex.toHexString(KeyUtils.toRawX25519PublicKeyBytes(publicKey)); + return hex(KeyUtils.toRawX25519PublicKeyBytes(publicKey)); } /** @@ -115,10 +116,10 @@ public class KeyUtilsTest { var expectedShared = "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"; byte[] sharedAliceToBob = KeyUtils.ecdh(alice_priv, bob_public); - assertEquals(expectedShared, Hex.toHexString(sharedAliceToBob)); + assertEquals(expectedShared, hex(sharedAliceToBob)); byte[] sharedBobToAlice = KeyUtils.ecdh(bob_priv, alice_pub); - assertEquals(expectedShared, Hex.toHexString(sharedBobToAlice)); + assertEquals(expectedShared, hex(sharedBobToAlice)); } // From https://github.com/google/wycheproof/blob/master/testvectors/x25519_test.json (tcId 32) @@ -145,7 +146,7 @@ public class KeyUtilsTest { var bob_public = xecPubFromHex( "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882bcf"); // note msb toggled in last byte var expectedShared = "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"; byte[] sharedAliceToBob = KeyUtils.ecdh(alice_priv, bob_public); - assertEquals(expectedShared, Hex.toHexString(sharedAliceToBob)); + assertEquals(expectedShared, hex(sharedAliceToBob)); } @Test diff --git a/security-utils/src/test/java/com/yahoo/security/SharedKeyTest.java b/security-utils/src/test/java/com/yahoo/security/SharedKeyTest.java index e63c0c48e9d..57c89c89665 100644 --- a/security-utils/src/test/java/com/yahoo/security/SharedKeyTest.java +++ b/security-utils/src/test/java/com/yahoo/security/SharedKeyTest.java @@ -1,7 +1,6 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.security; -import org.bouncycastle.util.encoders.Hex; import org.junit.jupiter.api.Test; import javax.crypto.CipherInputStream; @@ -12,6 +11,7 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; +import static com.yahoo.security.ArrayUtils.hex; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -52,7 +52,7 @@ public class SharedKeyTest { var theirSealed = SealedSharedKey.fromTokenString(publicToken); var theirShared = SharedKeyGenerator.fromSealedKey(theirSealed, receiverPrivate); - assertEquals(expectedSharedSecret, Hex.toHexString(theirShared.secretKey().getEncoded())); + assertEquals(expectedSharedSecret, hex(theirShared.secretKey().getEncoded())); } @Test |