/* 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);
}
}