简体   繁体   English

使用相同的参数进行加密可得出不同的结果

[英]Encryption with same parameters gives different results

Im sure there is a big mistake I am making here.... 我确定我在这里犯了一个大错误。

I am trying to encrypt a string using AES but passing the same parameters (plainText, password and salt) each time produces a different result. 我正在尝试使用AES加密字符串,但是每次传递相同的参数(plainText,密码和salt)会产生不同的结果。

I am calling as follows with the result of each being different: 我打电话如下,结果各不相同:

var cipherTextCode  = EncryptAes(plainTextCode, "K29V2NVsFhCVRYeJ88PJSdBd8Gd1PEXnWsX3lCKcy0y4M43oRq", "LQzJUNdsVgio20KnOPTdMONBO50FCCgOLXK5s7vpeX3Pr3fOu1");
var cipherTextCode1 = EncryptAes(plainTextCode, "K29V2NVsFhCVRYeJ88PJSdBd8Gd1PEXnWsX3lCKcy0y4M43oRq", "LQzJUNdsVgio20KnOPTdMONBO50FCCgOLXK5s7vpeX3Pr3fOu1");
var cipherTextCode2 = EncryptAes(plainTextCode, "K29V2NVsFhCVRYeJ88PJSdBd8Gd1PEXnWsX3lCKcy0y4M43oRq", "LQzJUNdsVgio20KnOPTdMONBO50FCCgOLXK5s7vpeX3Pr3fOu1");
var cipherTextCode3 = EncryptAes(plainTextCode, "K29V2NVsFhCVRYeJ88PJSdBd8Gd1PEXnWsX3lCKcy0y4M43oRq", "LQzJUNdsVgio20KnOPTdMONBO50FCCgOLXK5s7vpeX3Pr3fOu1");

The method I use to encrypt is as follows: 我用来加密的方法如下:

     private const int CB = 32;

   /// <summary>
        /// The initialization vector
        /// </summary>
        private readonly byte[] InitialisationVectorBytes = Encoding.ASCII.GetBytes("EAzjVfNrCzOoE7AI");

/// <summary>
        /// Encrypts a string using AES encryption
        /// </summary>
        /// <param name="plainText">The string to encrypt</param>
        /// <param name="passPhrase">The encryption key</param>
        /// <param name="salt">The encryption salt</param>
        /// <returns>an encrypted string</returns>
        private string EncryptAes(string plainText, string passPhrase, string salt)
        {
            try
            {
                //get the plain text bytes and the salt bytes
                var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
                var saltBytes = Encoding.UTF8.GetBytes(salt);

                //Derives the key from the phrase and the salt
                using(var password = new Rfc2898DeriveBytes(passPhrase, saltBytes))
                {
                    //use the AES Rijndael algorithm
                    using(var symmetricKey = new RijndaelManaged())
                    {
                        //set the mode
                        symmetricKey.Mode = CipherMode.CBC;

                        //create an encryption object
                        using(var encryptor = symmetricKey.CreateEncryptor(password.GetBytes(CB), InitialisationVectorBytes))
                        {
                            //create a memory stream
                            using(var memoryStream = new MemoryStream())
                            {
                                //create a cryptography stream
                                using(var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
                                {
                                    //encrypt the plain text
                                    cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
                                    cryptoStream.FlushFinalBlock();
                                    var cipherTextBytes = memoryStream.ToArray();
                                    return Convert.ToBase64String(cipherTextBytes);
                                }
                            }
                        }
                    }
                }
            }
            catch(SecurityException)
            {
                return string.Empty;
            }
        }

What am I doing wrong? 我究竟做错了什么?

A blockcipher like AES is a keyed permutation. 像AES这样的分组密码是密钥排列。 In the case of AES it takes a key and then turns a 16 byte block into another 16 byte block deterministically. 对于AES,它需要一个密钥,然后确定性地将一个16字节的块转换为另一个16字节的块。

To encrypt something with a block-cipher you need to use a mode of operation. 要使用分组密码加密某些内容,您需要使用一种操作模式。 Typically those modes take an IV (similar to a salt) which should be different for each message you encrypt. 通常,这些模式采用IV(类似于盐),对于您加密的每条消息,IV应该不同。 This difference in the IV leads to a totally different encrypted message. IV中的差异导致完全不同的加密消息。 Encrypting the same message with the same IV and key returns always the same ciphertext. 使用相同的IV和密钥加密相同的消息始终返回相同的密文。 Encrypting several messages with the same IV and key weakens security, but by how much depends on the mode. 使用相同的IV和密钥对几条消息进行加密会削弱安全性,但是取决于模式的程度。

The required properties for an IV depend on the chosen mode, sometimes it needs to be unique(eg for CTR mode), sometimes it needs to be unpredictably random (eg for CBC mode). IV所需的属性取决于所选模式,有时需要唯一(例如CTR模式),有时需要不可预测的随机性(例如CBC模式)。 But it generally doesn't have to be secret, so you send it to the recipient alongside the ciphertext, typically as a prefix. 但是它通常不必是秘密的,因此您通常将其与密文一起发送给收件人,通常作为前缀。

There are some modes designed for deterministic encryption. 有一些设计用于确定性加密的模式。 Using those modes you still leak if two messages are the same, but nothing more. 使用这些模式,如果两条消息相同,则仍然会泄漏,仅此而已。 You should only use those modes when you require determinism. 仅在需要确定性时才应使用这些模式。

In Short : You are using " symmetricKey.Mode = CipherMode.CBC;" 简而言之:您正在使用“ symmetricKey.Mode = CipherMode.CBC;” : unpredictably random. :不可预测的随机性。

if you want the same you can use : CipherMode.CTR 如果您希望相同,可以使用:CipherMode.CTR

credits : my source 学分: 我的来源

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM