/* This code is part of Freenet. It is distributed under the GNU General * Public License, version 2 (or at your option any later version). See * http://www.gnu.org/ for further details of the GPL. */ package freenet.crypt; import static org.junit.Assert.*; import java.security.GeneralSecurityException; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.KeyPair; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Security; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.junit.Test; import freenet.support.HexUtil; import freenet.support.Logger; public class KeyGenUtilsTest { private static final int trueLength = 16; private static final int falseLength = -1; private static final KeyType[] keyTypes = KeyType.values(); private static final byte[][] trueSecretKeys = { HexUtil.hexToBytes("20e86dc31ebf2c0e37670e30f8f45c57"), HexUtil.hexToBytes("8c6c2e0a60b3b73e9dbef076b68b686bacc9d20081e8822725d14b10b5034f48"), HexUtil.hexToBytes("33a4a38b71c8e350d3a98357d1bc9ecd"), HexUtil.hexToBytes("be56dbec20bff9f6f343800367287b48c0c28bf47f14b46aad3a32e4f24f0f5e"), HexUtil.hexToBytes("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"), HexUtil.hexToBytes("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"), HexUtil.hexToBytes("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"), HexUtil.hexToBytes("a92e3fa63e8cbe50869fb352d883911271bf2b0e9048ad04c013b20e901f5806"), HexUtil.hexToBytes("45d6c9656b3b115263ba12739e90dcc1"), HexUtil.hexToBytes("f468986cbaeecabd4cf242607ac602b51a1adaf4f9a4fc5b298970cbda0b55c6") }; private static final byte[][] trueLengthSecretKeys = { HexUtil.hexToBytes("20e86dc31ebf2c0e37670e30f8f45c57"), HexUtil.hexToBytes("8c6c2e0a60b3b73e9dbef076b68b686bacc9d20081e8822725d14b10b5034f48"), HexUtil.hexToBytes("33a4a38b71c8e350d3a98357d1bc9ecd"), HexUtil.hexToBytes("be56dbec20bff9f6f343800367287b48c0c28bf47f14b46aad3a32e4f24f0f5e"), HexUtil.hexToBytes("2e3e4a8f7c896ebf95fc3a59f283ca1e2808d984ad9043e710f74c4a8f4c8372"), HexUtil.hexToBytes("c9f1731f7e996603c6e1f8f72da8a66e51dd8bbc2465f1a9f4d32f800c41ac28" + "f99fe0c1d811678f91300cf33e527436"), HexUtil.hexToBytes("2ada39975c02c442e5ebc34832cde05e718acb28e15cdf80c8ab1da9c05bb53c" + "0b026c88a32aee65a924c9ea0b4e6cf5d2d434489d8bb82dfe7876919f690a56"), HexUtil.hexToBytes("a92e3fa63e8cbe50869fb352d883911271bf2b0e9048ad04c013b20e901f5806"), HexUtil.hexToBytes("45d6c9656b3b115263ba12739e90dcc1"), HexUtil.hexToBytes("f468986cbaeecabd4cf242607ac602b51a1adaf4f9a4fc5b298970cbda0b55c6") }; private static final KeyPairType[] trueKeyPairTypes = {KeyPairType.ECP256, KeyPairType.ECP384, KeyPairType.ECP521}; @SuppressWarnings("deprecation") private static final KeyPairType falseKeyPairType = KeyPairType.DSA; private static final byte[][] truePublicKeys = { HexUtil.hexToBytes("3059301306072a8648ce3d020106082a8648ce3d030107034200040126491fbe391419f" + "cdca058122a8520a816d3b7af9bc3a3af038e455b311b8234e5915ae2da11550a9f0ff9da5c65257" + "c95c2bd3d5c21bcf16f6c15a94a50cb"), HexUtil.hexToBytes("3076301006072a8648ce3d020106052b81040022036200043a095518fc49cfaf6feb5af" + "01cf71c02ebfff4fe581d93c6e252c8c607e6568db7267e0b958c4a262a6e6fa7c18572c3af59cd1" + "6535a28759d04488bae6c3014bbb4b89c25cbe3b76d7b540dabb13aed5793eb3ce572811b560bb18" + "b00a5ac93"), HexUtil.hexToBytes("30819b301006072a8648ce3d020106052b8104002303818600040076083359c8b0b34a9" + "03461e435188cb90f7501bcb7ed97e8c506c5b60ff21178a625f80f5729ed4746d8e83b28145a51b" + "9495880bf41b8ff0746ea0fe684832cc100ef1b01793c84abf64f31452d95bf0ef43d32440d8bc0d" + "67501fcffaf51ae4956e5ff22f3baffea5edddbebbeed0ec3b4af28d18568aaf97b5cd026f675388" + "1e0c4") }; private static PublicKey[] publicKeys = new PublicKey[truePublicKeys.length]; private static final byte[][] truePrivateKeys = { HexUtil.hexToBytes("3041020100301306072a8648ce3d020106082a8648ce3d030107042730250201010420f" + "8cb4b29aa51153ba811461e93fd1b2e69a127972f7100c5e246a3b2dcdd1b1c"), HexUtil.hexToBytes("304e020100301006072a8648ce3d020106052b81040022043730350201010430b88fe05" + "d03b20dca95f19cb0fbabdfef1211452b29527ccac2ea37236d31ab6e7cada08315c62912b5c17cd" + "f2d87fa3d"), HexUtil.hexToBytes("3060020100301006072a8648ce3d020106052b8104002304493047020101044201b4f57" + "3157d51f2e64a8b465fa92e52bae3529270951d448c18e4967beaa04b1f1fedb0e7a1e26f2eefb30" + "566a479e1194358670b044fae438d11717eb2a795c3a8") }; private static PrivateKey[] privateKeys = new PrivateKey[truePublicKeys.length]; private static final byte[] trueIV = new byte[16]; private static final String kdfInput = "testKey"; static{ Security.addProvider(new BouncyCastleProvider()); KeyPairType type; KeyFactory kf; X509EncodedKeySpec xks; PKCS8EncodedKeySpec pks; for(int i = 0; i < trueKeyPairTypes.length; i++){ try { type = trueKeyPairTypes[i]; kf = KeyFactory.getInstance(type.alg); xks = new X509EncodedKeySpec(truePublicKeys[i]); publicKeys[i] = kf.generatePublic(xks); pks = new PKCS8EncodedKeySpec(truePrivateKeys[i]); privateKeys[i] = kf.generatePrivate(pks); } catch (GeneralSecurityException e) { throw new Error(e); // Classpath error? } } } @Test public void testGenKeyPair() { for(KeyPairType type: trueKeyPairTypes){ assertNotNull("KeyPairType: "+type.name(), KeyGenUtils.genKeyPair(type)); } } @Test public void testGenKeyPairPublicKeyLength() { for(int i = 0; i < trueKeyPairTypes.length; i++){ KeyPairType type = trueKeyPairTypes[i]; byte[] publicKey = KeyGenUtils.genKeyPair(type).getPublic().getEncoded(); assertEquals("KeyPairType: "+type.name(), truePublicKeys[i].length, publicKey.length); } } @Test (expected = UnsupportedTypeException.class) public void testGenKeyPairDSAType() { KeyGenUtils.genKeyPair(falseKeyPairType); } @Test (expected = NullPointerException.class) public void testGenKeyPairNullInput() { KeyGenUtils.genKeyPair(null); } @Test public void testGetPublicKey() { for(int i = 0; i < trueKeyPairTypes.length; i++){ KeyPairType type = trueKeyPairTypes[i]; PublicKey key = KeyGenUtils.getPublicKey(type, truePublicKeys[i]); assertArrayEquals("KeyPairType: "+type.name(), key.getEncoded(), truePublicKeys[i]); } } @Test (expected = UnsupportedTypeException.class) public void testGetPublicKeyDSAType() { byte[] nullArray = null; KeyGenUtils.getPublicKey(falseKeyPairType, nullArray); } @Test (expected = NullPointerException.class) public void testGetPublicKeyNullInput1() { KeyGenUtils.getPublicKey(null, truePublicKeys[0]); } @Test (expected = NullPointerException.class) public void testGetPublicKeyNullInput2() { byte[] nullArray = null; KeyGenUtils.getPublicKey(trueKeyPairTypes[0], nullArray); } @Test public void testGetPublicKeyPair() { for(int i = 0; i < trueKeyPairTypes.length; i++){ KeyPairType type = trueKeyPairTypes[i]; KeyPair key = KeyGenUtils.getPublicKeyPair(type, truePublicKeys[i]); assertArrayEquals("KeyPairType: "+type.name(), key.getPublic().getEncoded(), truePublicKeys[i]); assertNull("KeyPairType: "+type.name(), key.getPrivate()); } } @Test public void testGetPublicKeyPairNotNull() { for(int i = 0; i < trueKeyPairTypes.length; i++){ KeyPairType type = trueKeyPairTypes[i]; assertNotNull("KeyPairType: "+type.name(), KeyGenUtils.getPublicKey(type, truePublicKeys[i])); } } @Test (expected = UnsupportedTypeException.class) public void testGetPublicKeyPairDSAType() { byte[] nullArray = null; KeyGenUtils.getPublicKeyPair(falseKeyPairType, nullArray); } @Test (expected = NullPointerException.class) public void testGetPublicKeyPairNullInput1() { KeyGenUtils.getPublicKeyPair(null, truePublicKeys[0]); } @Test (expected = NullPointerException.class) public void testGetPublicKeyPairNullInput2() { byte[] nullArray = null; KeyGenUtils.getPublicKeyPair(trueKeyPairTypes[0], nullArray); } @Test public void testGetKeyPairKeyPairTypeByteArrayByteArray() { for(int i = 0; i < trueKeyPairTypes.length; i++){ KeyPairType type = trueKeyPairTypes[i]; assertNotNull("KeyPairType: "+type.name(), KeyGenUtils.getKeyPair(type, truePublicKeys[i], truePrivateKeys[i])); } } @Test (expected = UnsupportedTypeException.class) public void testGetKeyPairKeyPairTypeByteArrayDSAType() { byte[] nullArray = null; KeyGenUtils.getKeyPair(falseKeyPairType, nullArray, nullArray); } @Test (expected = NullPointerException.class) public void testGetKeyPairKeyPairTypeByteArrayNullInput1() { KeyGenUtils.getKeyPair(null, truePublicKeys[0], truePrivateKeys[0]); } @Test (expected = NullPointerException.class) public void testGetKeyPairKeyPairTypeByteArrayNullInput2() { KeyGenUtils.getKeyPair(trueKeyPairTypes[0], null, truePrivateKeys[0]); } @Test (expected = NullPointerException.class) public void testGetKeyPairKeyPairTypeByteArrayNullInput3() { KeyGenUtils.getKeyPair(trueKeyPairTypes[0], truePublicKeys[0], null); } @Test public void testGetKeyPairPublicKeyPrivateKey() { for(int i = 0; i < trueKeyPairTypes.length; i++){ assertNotNull("KeyPairType: "+trueKeyPairTypes[i].name(), KeyGenUtils.getKeyPair(publicKeys[i], privateKeys[i])); } } @Test public void testGetKeyPairPublicKeyPrivateKeySamePublic() { for(int i = 0; i < trueKeyPairTypes.length; i++){ KeyPair pair = KeyGenUtils.getKeyPair(publicKeys[i], privateKeys[i]); assertEquals("KeyPairType: "+trueKeyPairTypes[i].name(), pair.getPublic(), publicKeys[i]); } } @Test public void testGetKeyPairPublicKeyPrivateKeySamePrivate() { for(int i = 0; i < trueKeyPairTypes.length; i++){ KeyPair pair = KeyGenUtils.getKeyPair(publicKeys[i], privateKeys[i]); assertEquals("KeyPairType: "+trueKeyPairTypes[i].name(), pair.getPrivate(), privateKeys[i]); } } @Test public void testGenSecretKey() { for(KeyType type: keyTypes){ assertNotNull("KeyType: "+type.name(), KeyGenUtils.genSecretKey(type)); } } @Test public void testGenSecretKeyKeySize() { for(KeyType type: keyTypes){ byte[] key = KeyGenUtils.genSecretKey(type).getEncoded(); System.out.println(key.length); int keySizeBytes = type.keySize >> 3; assertEquals("KeyType: "+type.name(), keySizeBytes, key.length); } } @Test (expected = NullPointerException.class) public void testGenSecretKeyNullInput() { KeyGenUtils.genSecretKey(null); } @Test public void testGetSecretKey() { for(int i = 0; i < keyTypes.length; i++){ KeyType type = keyTypes[i]; SecretKey newKey = KeyGenUtils.getSecretKey(type, trueLengthSecretKeys[i]); assertArrayEquals("KeyType: "+type.name(), trueLengthSecretKeys[i], newKey.getEncoded()); } } @Test (expected = NullPointerException.class) public void testGetSecretKeyNullInput1() { byte[] nullArray = null; KeyGenUtils.getSecretKey(keyTypes[1], nullArray); } @Test (expected = NullPointerException.class) public void testGetSecretKeyNullInput2() { KeyGenUtils.getSecretKey(null, trueSecretKeys[0]); } @Test public void testGenNonceLength() { assertEquals(KeyGenUtils.genNonce(trueLength).capacity(), trueLength); } @Test (expected = NegativeArraySizeException.class) public void testGenNonceNegativeLength() { KeyGenUtils.genNonce(falseLength); } @Test public void testGenIV() { assertEquals(KeyGenUtils.genIV(trueLength).getIV().length, trueLength); } @Test (expected = NegativeArraySizeException.class) public void testGenIVNegativeLength() { KeyGenUtils.genIV(falseLength); } @Test public void testGetIvParameterSpecLength() { assertEquals(KeyGenUtils.getIvParameterSpec(new byte[16], 0, trueLength).getIV().length, trueLength); } @Test (expected = IllegalArgumentException.class) public void testGetIvParameterSpecNullInput() { KeyGenUtils.getIvParameterSpec(null, 0, trueIV.length); } @Test (expected = ArrayIndexOutOfBoundsException.class) public void testGetIvParameterSpecOffsetOutOfBounds() { KeyGenUtils.getIvParameterSpec(trueIV, -4, trueIV.length); } @Test (expected = IllegalArgumentException.class) public void testGetIvParameterSpecLengthOutOfBounds() { KeyGenUtils.getIvParameterSpec(trueIV, 0, trueIV.length+20); } @Test public void testDeriveSecretKey() throws InvalidKeyException{ SecretKey kdfKey = KeyGenUtils.getSecretKey(KeyType.HMACSHA512, trueLengthSecretKeys[6]); SecretKey buf1 = KeyGenUtils.deriveSecretKey(kdfKey, KeyGenUtils.class, kdfInput, KeyType.HMACSHA512); SecretKey buf2 = KeyGenUtils.deriveSecretKey(kdfKey, KeyGenUtils.class, kdfInput, KeyType.HMACSHA512); assertNotNull(buf1); assertTrue(buf1.equals(buf2)); } @Test public void testDeriveSecretKeyLength() throws InvalidKeyException{ for(KeyType type: keyTypes){ SecretKey kdfKey = KeyGenUtils.getSecretKey(KeyType.HMACSHA512, trueLengthSecretKeys[6]); SecretKey buf1 = KeyGenUtils.deriveSecretKey(kdfKey, KeyGenUtils.class, kdfInput, type); assertEquals(buf1.getEncoded().length, type.keySize >> 3); } } @Test (expected = InvalidKeyException.class) public void testDeriveSecretKeyNullInput1() throws InvalidKeyException { SecretKey kdfKey = null; KeyGenUtils.deriveSecretKey(kdfKey, KeyGenUtils.class, kdfInput, KeyType.ChaCha128); } @Test (expected = NullPointerException.class) public void testDeriveSecretKeyNullInput2() throws InvalidKeyException{ SecretKey kdfKey = KeyGenUtils.getSecretKey(KeyType.HMACSHA512, trueLengthSecretKeys[6]); KeyGenUtils.deriveSecretKey(kdfKey, null, kdfInput, KeyType.ChaCha128); } @Test (expected = NullPointerException.class) public void testDeriveSecretKeyNullInput3() throws InvalidKeyException{ SecretKey kdfKey = KeyGenUtils.getSecretKey(KeyType.HMACSHA512, trueLengthSecretKeys[6]); KeyGenUtils.deriveSecretKey(kdfKey, KeyGenUtils.class, null, KeyType.ChaCha128); } @Test (expected = NullPointerException.class) public void testDeriveSecretKeyNullInput4() throws InvalidKeyException{ SecretKey kdfKey = KeyGenUtils.getSecretKey(KeyType.HMACSHA512, trueLengthSecretKeys[6]); KeyGenUtils.deriveSecretKey(kdfKey, KeyGenUtils.class, kdfInput, null); } @Test public void testDeriveIvParameterSpec() throws InvalidKeyException{ SecretKey kdfKey = KeyGenUtils.getSecretKey(KeyType.HMACSHA512, trueLengthSecretKeys[6]); IvParameterSpec buf1 = KeyGenUtils.deriveIvParameterSpec(kdfKey, KeyGenUtils.class, kdfInput, KeyType.ChaCha128); IvParameterSpec buf2 = KeyGenUtils.deriveIvParameterSpec(kdfKey, KeyGenUtils.class, kdfInput, KeyType.ChaCha128); assertNotNull(buf1); assertArrayEquals(buf1.getIV(), buf2.getIV()); } @Test public void testDeriveIvParameterSpecLength() throws InvalidKeyException{ for(KeyType type: keyTypes){ SecretKey kdfKey = KeyGenUtils.getSecretKey(KeyType.HMACSHA512, trueLengthSecretKeys[6]); IvParameterSpec buf1 = KeyGenUtils.deriveIvParameterSpec(kdfKey, KeyGenUtils.class, kdfInput, type); assertEquals(buf1.getIV().length, type.ivSize >> 3); } } @Test (expected = InvalidKeyException.class) public void testDeriveIvParameterSpecNullInput1() throws InvalidKeyException { SecretKey kdfKey = null; KeyGenUtils.deriveIvParameterSpec(kdfKey, KeyGenUtils.class, kdfInput, KeyType.ChaCha128); } @Test (expected = NullPointerException.class) public void testDeriveIvParameterSpecNullInput2() throws InvalidKeyException{ SecretKey kdfKey = KeyGenUtils.getSecretKey(KeyType.HMACSHA512, trueLengthSecretKeys[6]); KeyGenUtils.deriveIvParameterSpec(kdfKey, null, kdfInput, KeyType.ChaCha128); } @Test (expected = NullPointerException.class) public void testDeriveIvParameterSpecNullInput3() throws InvalidKeyException{ SecretKey kdfKey = KeyGenUtils.getSecretKey(KeyType.HMACSHA512, trueLengthSecretKeys[6]); KeyGenUtils.deriveIvParameterSpec(kdfKey, KeyGenUtils.class, null, KeyType.ChaCha128); } @Test (expected = NullPointerException.class) public void testDeriveIvParameterSpecNullInput4() throws InvalidKeyException{ SecretKey kdfKey = KeyGenUtils.getSecretKey(KeyType.HMACSHA512, trueLengthSecretKeys[6]); KeyGenUtils.deriveIvParameterSpec(kdfKey, KeyGenUtils.class, kdfInput, null); } }