/// <summary>
 ///     Create a SymmetricAlgorithm which logs the encryption operation of the input algorithm, but
 ///     does not monitor for thread safe access to the object.
 /// </summary>
 public static SymmetricAlgorithm EnableLogging(this SymmetricAlgorithm loggedAlgorithm)
 {
     return(loggedAlgorithm.EnableLogging(new SymmetricAlgorithmDiagnosticOptions()
     {
         CheckThreadSafety = false
     }));
 }
        /// <summary>
        ///     Utility to encapsulate round-tripping ciphertext
        /// </summary>
        private static bool RoundTripHelper(Type encryptionAlgorithm,
                                            Action <SymmetricAlgorithm> encryptionSetup,
                                            Type decryptionAlgorithm,
                                            Action <SymmetricAlgorithm> decryptionSetup)
        {
            // Encryption parameters
            byte[]      key         = null;
            byte[]      iv          = null;
            CipherMode  cipherMode  = CipherMode.CBC;
            PaddingMode paddingMode = PaddingMode.None;

            // Round tripping data
            byte[] plainText  = Encoding.UTF8.GetBytes("Secret round trip message");
            byte[] cipherText = null;
            SymmetricEncryptionState encryptionState = null;

            SymmetricAlgorithm encryptionObject = null;

            try
            {
                // Setup the encryption algorithm
                encryptionObject = (SymmetricAlgorithm)Activator.CreateInstance(encryptionAlgorithm);
                encryptionSetup(encryptionObject);
                encryptionObject = encryptionObject.EnableLogging();

                // Encrypt the data
                using (MemoryStream ms = new MemoryStream())
                    using (CryptoStream cs = new CryptoStream(ms, encryptionObject.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(plainText, 0, plainText.Length);
                        cs.FlushFinalBlock();

                        cipherText = ms.ToArray();
                    }

                // Save the encryption parameters
                key             = encryptionObject.Key;
                iv              = encryptionObject.IV;
                cipherMode      = encryptionObject.Mode;
                paddingMode     = encryptionObject.Padding;
                encryptionState = encryptionObject.GetLastEncryptionState();
            }
            finally
            {
                if (encryptionObject != null)
                {
                    (encryptionObject as IDisposable).Dispose();
                }
            }

            byte[] roundTrip = null;

            // Now verify the data
            SymmetricAlgorithm decryptionObject = null;

            try
            {
                decryptionObject = (SymmetricAlgorithm)Activator.CreateInstance(decryptionAlgorithm);

                decryptionObject.Key     = key;
                decryptionObject.IV      = iv;
                decryptionObject.Mode    = cipherMode;
                decryptionObject.Padding = paddingMode;

                decryptionSetup(decryptionObject);
                decryptionObject = decryptionObject.EnableDecryptionVerification(encryptionState);

                using (MemoryStream ms = new MemoryStream())
                    using (CryptoStream cs = new CryptoStream(ms, decryptionObject.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(cipherText, 0, cipherText.Length);
                        cs.FlushFinalBlock();

                        roundTrip = ms.ToArray();
                    }
            }
            finally
            {
                if (decryptionObject != null)
                {
                    (decryptionObject as IDisposable).Dispose();
                }
            }

            if (roundTrip.Length != plainText.Length)
            {
                return(false);
            }

            for (int i = 0; i < roundTrip.Length; ++i)
            {
                if (roundTrip[i] != plainText[i])
                {
                    return(false);
                }
            }

            return(true);
        }