I'm trying to use an asymmetric private and public key combination to generate a symmetric key for encrypting and decrypting some text, but, I'm stuck unable to use the generated key as it is 128bytes in size and this is unacceptable for the AES encryption. I'd like to solve this problem using just the JRE (no external libraries). Do you have a solution?
I've included my example code below, there's a comment indicating the line I get the exception thrown.
(encryptCipher.init(Cipher.ENCRYPT_MODE, tomSecretKeySpec, iv);
)
I read about KDF hashing, but Java doesn't seem to have an obvious way of invoking this on my 128byte key. Also, Im not sure this is the right answer since my understanding is that the longer the key, the more secure the encryption (for a given algorithm). Perhaps I need to switch from using AES/CBC/PKCS5Padding, but none of the other algorithms included with the JDK as standard seem to support the 128byte key either.
public void demoSymmetricEncryption() throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, InvalidAlgorithmParameterException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException {
String keyAlgorithm = "DiffieHellman";
String keyAgreementAlgorithm = "DiffieHellman";
String keySpecAlgorithm = "AES";
String cipherAlgorithm = "AES/CBC/PKCS5Padding";
KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(keyAlgorithm);
keyGenerator.initialize(1024, new SecureRandom());
KeyPair tomKeyPair = keyGenerator.generateKeyPair();
PrivateKey tomPrivateKey = tomKeyPair.getPrivate();
PublicKey tomPublicKey = tomKeyPair.getPublic();
KeyPair steveKeyPair = keyGenerator.generateKeyPair();
PrivateKey stevePrivateKey = steveKeyPair.getPrivate();
PublicKey stevePublicKey = steveKeyPair.getPublic();
int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
System.out.println("Limited encryption policy files installed : " + (maxKeyLen == 128)); // returns false
KeyAgreement tomKeyAgreement = KeyAgreement.getInstance(keyAgreementAlgorithm);
keyGenerator.initialize(1024, new SecureRandom());
tomKeyAgreement.init(tomPrivateKey);
tomKeyAgreement.doPhase(stevePublicKey, true);
byte[] tomSecret = tomKeyAgreement.generateSecret();
SecretKeySpec tomSecretKeySpec = new SecretKeySpec(tomSecret, keySpecAlgorithm);
KeyAgreement steveKeyAgreement = KeyAgreement.getInstance(keyAgreementAlgorithm);
steveKeyAgreement.init(stevePrivateKey);
steveKeyAgreement.doPhase(tomPublicKey, true);
byte[] steveSecret = steveKeyAgreement.generateSecret();
SecretKeySpec steveSecretKeySpec = new SecretKeySpec(steveSecret, keySpecAlgorithm);
System.out.println("Secret Keys are identical : " + steveSecretKeySpec.equals(tomSecretKeySpec)); // returns true
String initVector = "RandomInitVector";
Cipher encryptCipher = Cipher.getInstance(cipherAlgorithm);
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
// fails because AES key is 128 bytes not 128 bits in length - think I need to use KDF hash to shrink it appropriately.
encryptCipher.init(Cipher.ENCRYPT_MODE, tomSecretKeySpec, iv);
// Attempt to use the cipher
byte[] encryptedData = encryptCipher.doFinal("Hello".getBytes());
Cipher decryptCipher = Cipher.getInstance(cipherAlgorithm);
iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
decryptCipher.init(Cipher.DECRYPT_MODE, steveSecretKeySpec, iv);
byte[] decryptedData = decryptCipher.doFinal(encryptedData);
System.out.println("Decrypted Data : " + new String(decryptedData));
}
The output from the program is as follows:
Limited encryption policy files installed : false
Secret Keys are identical : true
Exception in thread "main" java.security.InvalidKeyException: Invalid AES key length: 128 bytes
at com.sun.crypto.provider.AESCrypt.init(AESCrypt.java:87)
at com.sun.crypto.provider.CipherBlockChaining.init(CipherBlockChaining.java:91)
at com.sun.crypto.provider.CipherCore.init(CipherCore.java:582)
at com.sun.crypto.provider.AESCipher.engineInit(AESCipher.java:339)
at javax.crypto.Cipher.implInit(Cipher.java:806)
at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
at javax.crypto.Cipher.init(Cipher.java:1396)
at javax.crypto.Cipher.init(Cipher.java:1327)
at crypto.SymetricEncryptionTest.demoSymmetricEncryption(SymetricEncryptionTest.java:76)
at crypto.SymetricEncryptionTest.main(SymetricEncryptionTest.java:29)