I have a problem with AES encryption. I need to encrypt plaintext using CTR with a random IV. Then I need to encrypt the IV with the same key. I know that it is not required to encrypt the IV, but I need it for my usecase.
To decrypt the message I simply first decrypt the IV and then decrypt the cipher with the decrypted IV and the key.
Currently I am using EBC to encrypt the IV, as otherwhise I would need another IV to encrypt the previous IV and so on.
The problem is that I am able to decrypt the cipher using a a completely different key from the enryption.
What am I doing wrong?
import java.security.SecureRandom;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
public static void main(String[] args) throws Exception {
//Generate a random AES Key
SecretKey key1 = generateAESKey();
byte[] plainText = "some plain text".getBytes();
//Gerate random IV
byte[] iv = new byte[16];
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
//Encrypt plainText using the generated key1 using CTR
byte[] encryptedWithKey1 = encryptCTR(plainText, iv, key1);
//Now encrypt the IV using key1 with ECB
byte[] encryptedIvWithKey1 = encryptECB(iv, key1);
//Generate another key
SecretKey key2 = generateAESKey();
//First decrypt IV with wrong key, which resuts in wrong IV
byte[] decryptedIvWithKey2 = decryptECB(encryptedIvWithKey1, key2);
//Using this wrong IV decrypt encrypted payload with wrong key
byte[] decryptedWithKey2 = decryptCTR(encryptedWithKey1, decryptedIvWithKey2, key2);
//Expect plaintext and decrypted cipher using wrong key to NOT be equal
System.out.println("should print false: " + Arrays.equals(plainText, decryptedWithKey2));
}
private static byte[] encryptCTR(byte[] plainText, byte[] iv, SecretKey key) throws Exception {
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);
return cipher.doFinal(plainText);
}
private static byte[] decryptCTR(byte[] encrypted, byte[] iv, SecretKey key) throws Exception {
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
Cipher cipherDecrypt = Cipher.getInstance("AES/CTR/NoPadding");
cipherDecrypt.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
return cipherDecrypt.doFinal(encrypted);
}
private static byte[] encryptECB(byte[] plainText, SecretKey key) throws Exception {
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(plainText);
}
private static byte[] decryptECB(byte[] encrypted, SecretKey key) throws Exception {
Cipher cipherDecrypt = Cipher.getInstance("AES/ECB/NoPadding");
cipherDecrypt.init(Cipher.DECRYPT_MODE, key);
return cipherDecrypt.doFinal(encrypted);
}
public static SecretKey generateAESKey() {
SecureRandom random = new SecureRandom();
byte[] keyBytes = new byte[16];
random.nextBytes(keyBytes);
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
return key;
}