AES encryption and decryption in Java
I'm pretty new to encryption/decryption and have to encrypt some data files, but not entirely sure I'm going about it the right way. Right now, I have a script to encrypt all files that are not included in my repository, but the decryptor is included in the repository, and the encryption key is read in as an environment variable. I'm assuming that even including the decryptor in the repo is incorrect, since the algorithm/mode/padding is visible in the code as shown below.
Besides that, after some research, it looks like if an attacker knows the initialization vector, they will be able to decrypt the first block in the encrypted file. do i understand? Also, I've read that the vector should be randomly generated every time, but I don't know how to do this since the encryptor will only run once unless I change how the file is encrypted.
One last question... does it make sense to set another environment variable to store the initialization vector being used? Due to the randomness of the vector to look for, I don't think.
private static byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
private static IvParameterSpec ivspec = new IvParameterSpec(iv);
private static byte[] decodedKey = Base64.getDecoder().decode(System.getenv("SECRET_KEY"));
private static SecretKey originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES");
//any encrypted input file that is not a database will be read in as an input stream
public static CipherInputStream decryptInputStream(InputStream inputStream) {
try{
// Initialize the cipher by specifying the algorithm/mode/padding
Cipher aes2 = Cipher.getInstance("AES/CBC/PKCS5Padding");
//
aes2.init(Cipher.DECRYPT_MODE, originalKey, ivspec);
CipherInputStream in = new CipherInputStream(inputStream, aes2);
return in;
} catch(NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException e){
logger.info(e.getMessage());
return null;
}
}
But I'm not sure I'm going about it the right way.
I have some examples of my own using cryptocurrencies .
Besides the static IV (already commented), you're missing some form of integrity control (each for "authenticated encryption"). This can be achieved using modes with built-in integrity (eg AES-CGM) or using HMAC.
I'm assuming that even including the decryptor in the repo is incorrect, since the algorithm/mode/padding is visible in the code as shown below.
Whether the algorithm/pattern/padding is visible or not has no effect on solution security. The only thing you need to protect is the key.
Besides that, after some research, it looks like if an attacker knows the initialization vector, they will be able to decrypt the first block in the encrypted file.
This is not true. The IV must be unique (for CBC, the IV must be unpredictable/random) for each encryption operation performed with the same key (thx Maarten). A known IV doesn't help an attacker decrypt anything.
As mentioned earlier, the IV is usually passed as part of the ciphertext. Often, the encrypted result looks like IV || ciphertext || MAC
it ||
represents a concatenation. The size of the IV and MAC are fixed, so when decrypting, splitting the parameters is simple.
do i understand? Also, I read that the vector should be randomly generated each time
affim
So the IV should only be randomly assigned between files, not between runs?
The whole point of using IVs is that there are some weaknesses in security if multiple inputs are encrypted with the same key. In practice, this weakness can be avoided by using a unique or random IV.