Good AES Initialization Vector practice

The IV should be random and unique for every run of your encryption method. Deriving it from the key/message or hard-coding it is not sufficiently secure. The IV can be generated within this method, instead of passed into it, and written to the output stream prior to the encrypted data.

When decrypting, the IV can then be read from the input before the encrypted data.


When Encrypting, generate your IV and pre-pend it to the cipher text (something like this)

        using (var aes= new AesCryptoServiceProvider()
        {
            Key = PrivateKey,
            Mode = CipherMode.CBC,
            Padding = PaddingMode.PKCS7
        })
        {

            var input = Encoding.UTF8.GetBytes(originalPayload);
            aes.GenerateIV();
            var iv = aes.IV;
            using (var encrypter = aes.CreateEncryptor(aes.Key, iv))
            using (var cipherStream = new MemoryStream())
            {
                using (var tCryptoStream = new CryptoStream(cipherStream, encrypter, CryptoStreamMode.Write))
                using (var tBinaryWriter = new BinaryWriter(tCryptoStream))
                {
                    //Prepend IV to data
                    //tBinaryWriter.Write(iv); This is the original broken code, it encrypts the iv
                    cipherStream.Write(iv);  //Write iv to the plain stream (not tested though)
                    tBinaryWriter.Write(input);
                    tCryptoStream.FlushFinalBlock();
                }

                string encryptedPayload = Convert.ToBase64String(cipherStream.ToArray());
            }

        }

When decrypting this back, get first 16 bytes out and use it in crypto stream

var aes= new AesCryptoServiceProvider()
                    {
                        Key = PrivateKey,
                        Mode = CipherMode.CBC,
                        Padding = PaddingMode.PKCS7
                    };

                    //get first 16 bytes of IV and use it to decrypt
                    var iv = new byte[16];
                    Array.Copy(input, 0, iv, 0, iv.Length);

                    using (var ms = new MemoryStream())
                    {
                        using (var cs = new CryptoStream(ms, aes.CreateDecryptor(aes.Key, iv), CryptoStreamMode.Write))
                        using (var binaryWriter = new BinaryWriter(cs))
                        {
                            //Decrypt Cipher Text from Message
                            binaryWriter.Write(
                                input,
                                iv.Length,
                                input.Length - iv.Length
                            );
                        }

                        return Encoding.Default.GetString(ms.ToArray());
                    }