Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用相同参数的加密会产生不同的结果_C#_Encryption_Aes - Fatal编程技术网

C# 使用相同参数的加密会产生不同的结果

C# 使用相同参数的加密会产生不同的结果,c#,encryption,aes,C#,Encryption,Aes,我确信我在这里犯了一个很大的错误 我尝试使用AES加密字符串,但每次传递相同的参数(明文、密码和salt)会产生不同的结果 我打电话如下,结果各不相同: var cipherTextCode = EncryptAes(plainTextCode, "K29V2NVsFhCVRYeJ88PJSdBd8Gd1PEXnWsX3lCKcy0y4M43oRq", "LQzJUNdsVgio20KnOPTdMONBO50FCCgOLXK5s7vpeX3Pr3fOu1"); var cipherTextCo

我确信我在这里犯了一个很大的错误

我尝试使用AES加密字符串,但每次传递相同的参数(明文、密码和salt)会产生不同的结果

我打电话如下,结果各不相同:

var cipherTextCode  = EncryptAes(plainTextCode, "K29V2NVsFhCVRYeJ88PJSdBd8Gd1PEXnWsX3lCKcy0y4M43oRq", "LQzJUNdsVgio20KnOPTdMONBO50FCCgOLXK5s7vpeX3Pr3fOu1");
var cipherTextCode1 = EncryptAes(plainTextCode, "K29V2NVsFhCVRYeJ88PJSdBd8Gd1PEXnWsX3lCKcy0y4M43oRq", "LQzJUNdsVgio20KnOPTdMONBO50FCCgOLXK5s7vpeX3Pr3fOu1");
var cipherTextCode2 = EncryptAes(plainTextCode, "K29V2NVsFhCVRYeJ88PJSdBd8Gd1PEXnWsX3lCKcy0y4M43oRq", "LQzJUNdsVgio20KnOPTdMONBO50FCCgOLXK5s7vpeX3Pr3fOu1");
var cipherTextCode3 = EncryptAes(plainTextCode, "K29V2NVsFhCVRYeJ88PJSdBd8Gd1PEXnWsX3lCKcy0y4M43oRq", "LQzJUNdsVgio20KnOPTdMONBO50FCCgOLXK5s7vpeX3Pr3fOu1");
我用于加密的方法如下所示:

     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;
            }
        }
private const int CB=32;
/// 
///初始化向量
/// 
私有只读字节[]InitialisationVectorBytes=Encoding.ASCII.GetBytes(“EAzjVfNrCzOoE7AI”);
/// 
///使用AES加密对字符串进行加密
/// 
///要加密的字符串
///加密密钥
///加密盐
///加密字符串
私有字符串EncryptAes(字符串明文、字符串密码短语、字符串salt)
{
尝试
{
//获取纯文本字节和salt字节
var plainTextBytes=Encoding.UTF8.GetBytes(明文);
var saltBytes=Encoding.UTF8.GetBytes(salt);
//从短语和盐中派生出键
使用(var password=new Rfc2898DeriveBytes(密码短语,saltBytes))
{
//使用AES Rijndael算法
使用(var symmetricKey=new RijndaelManaged())
{
//设置模式
symmetricKey.Mode=CipherMode.CBC;
//创建加密对象
使用(var encryptor=symmetricKey.CreateEncryptor(password.GetBytes(CB),InitialisationVectorBytes))
{
//创建一个内存流
使用(var memoryStream=new memoryStream())
{
//创建加密流
使用(var cryptoStream=new cryptoStream(memoryStream,encryptor,CryptoStreamMode.Write))
{
//加密纯文本
cryptoStream.Write(明文字节,0,明文字节.Length);
cryptoStream.FlushFinalBlock();
var cipherTextBytes=memoryStream.ToArray();
返回Convert.tobase64字符串(cipherTextBytes);
}
}
}
}
}
}
catch(SecurityException)
{
返回字符串。空;
}
}

我做错了什么?

像AES这样的块密码是密钥置换。在AES的情况下,它需要一个键,然后将一个16字节的块决定性地转换成另一个16字节的块

要用分组密码加密某些东西,需要使用一种操作模式。通常,这些模式采用IV(类似于salt),对于您加密的每条消息,IV应该是不同的。IV中的这种差异导致了完全不同的加密消息。使用相同的IV和密钥加密相同的消息时,总是返回相同的密文。使用相同的IV和密钥加密多条消息会削弱安全性,但程度取决于模式

IV所需的属性取决于选择的模式,有时需要唯一(例如CTR模式),有时需要不可预测的随机性(例如CBC模式)。但是它通常不必是秘密的,所以你把它和密文一起发送给收件人,通常作为前缀

有一些模式是为确定性加密设计的。使用这些模式,如果两条消息相同,但仅此而已,则仍然会泄漏。只有在需要决定论时,才应该使用这些模式

简而言之:您正在使用“symmetricKey.Mode=CipherMode.CBC;”:不可预测的随机

如果您想要相同的,可以使用:CipherMode.CTR


信用证:

我不知道您当前的问题,但您不应该在实际实现中重用IVs。您没有发布(我假设)AES的代码还有其他问题,您需要为“RijndaelManaged
指定128位的块大小。用十六进制检查
symmetricKey`(名称很差)的所有参数。@StevenWood您还有更多信息或东西要添加吗?你有没有看过我用你的代码贴出的小提琴,得到了不同的结果?OP使用的是CBC,但每次调用都使用相同的
IV
,使用当前的(糟糕的)实现,OP应该得到相同的加密位是吗?你真的是直接从这里复制的吗?克里特纳:即使使用相同的IV,CBC也是随机的。参见资料来源:@PoorBeggar no.AES是确定性的。我已经阅读了资料来源,CBC在每次调用时生成不同的密码文本,假设您为每次调用提供不同的IV,OP没有这样做-这本身就是一个问题,但不是OP所问的主要问题