1

I am fairly new to encryption/decryption and have to encrypt some data files, but am not entirely sure I am going about it the right way. Right now, I have a script to encrypt all the files, which is not included in my repo, but the decrypter is included in the repo and the encryption key is read in as an environment variable. I'm assuming even including the decrypter in the repo is bad practice because the algorithm/mode/padding is visible within the code as you can see below.

Aside from that, after some research, it looks like if an attacker knows the initialization vector, they would be able to decrypt the first block in the encrypted file. Am I understanding that right? Also, I have read that the vector should be randomly generated each time but I do not understand how I can do this considering the encrypter would only be run once unless I change the way I go about encrypting files.

One last question...would it make sense to have another environment variable to store the initialization vector being used? I assume not, because of the randomization of the vector being sought after.

    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;
        }
    }
4
  • You should use a different initialization vector (IV) for each file. The IV should be stored with the encrypted file. Without the secret key, an attacker can't do anything even if they have the encryption and decryption code. Keep your key out of the repo and on a hardware token (maybe your brain). Most likely, you'll be better off using a standardized format, and finding an existing tool that supports it; even OpenSSL has command line tools that are adequate for this. Commented Dec 16, 2019 at 17:28
  • So, the IV should only be randomized between files and not between runs? What is the point of randomizing it if it can be viewed from within the file? The key would not be in the repo as it is an environment variable on the server and the server is locked behind an Oauth protocol. Commented Dec 16, 2019 at 17:40
  • 1
    The point of the IV is that even if multiple messages contain identical blocks, they will be different after encryption. So you need a different IV for each message (output file). Commented Dec 16, 2019 at 18:49
  • Yes, and besides leaking which blocks are identical, it will obviously also leak where files start to differ. That could be valuable information to an attacker. Any leakage of data apart from message / file size is considered a problem for ciphers. Of course, file size also leaks information, so you should be aware that this kind of information may be leaked. Similar for non-encrypted meta attributes (access / change times of the file, to name just one thing). Commented Dec 17, 2019 at 11:56

1 Answer 1

1

but am not entirely sure I am going about it the right way.

I have a few examples of my own for using crypto.

Aside static IV (already commented) you are missing some form of integrity control (seach for "authenticated encryption"). It can be achieved using modes with integrity built-in (such as AES-CGM) or using HMAC.

I'm assuming even including the decrypter in the repo is bad practice because the algorithm/mode/padding is visible within the code as you can see below.

Whether algorithm/mode/padding is visible should have no effect on the solution security. The only thing you need to protect is the key.

Aside from that, after some research, it looks like if an attacker knows the initialization vector, they would be able to decrypt the first block in the encrypted file.

That's not true. IV needs to be unique (and for CBC the IV needs to be unpredictable/random) for each encryption operation performed with the same key (thx Maarten). Known IV doesn't help attacker to decrypt anything.

As already commented - IV is usually passed as part of the ciphertext. Very often the encryption result looks like IV || ciphertext || MAC where || is denoting concatenation. Size of IV and MAC are fixed, so when decrypting, it's simple to split the parameters.

Am I understanding that right? Also, I have read that the vector should be randomly generated each time

Affirmative

So, the IV should only be randomized between files and not between runs?

The whole point in using IV is that there are some weaknesses in security if you encrypt multiple inputs using the same key. Using unique or random IV actually prevents this sort of weaknesses.

Sign up to request clarification or add additional context in comments.

1 Comment

"IV needs to be unique" ... for each encryption operation performed with the same key.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.