C# 我的AES初始化向量似乎与C中的AES CryptoServiceProvider无关#

C# 我的AES初始化向量似乎与C中的AES CryptoServiceProvider无关#,c#,encryption,aescryptoserviceprovider,C#,Encryption,Aescryptoserviceprovider,我一直在做一些关于在C#中使用AESCryptServiceProvider的研究。到目前为止,我有一个实现,它似乎正在工作。然而,我对初始化向量的理解是,当有效负载和密钥相同时,它应该保护我的密文不被相同,但似乎我做错了什么。更改初始化向量似乎根本不会影响这些函数的结果 以下是我的职能: public string EncryptString(string toEncrypt, byte[] encryptionKey, byte[] iv) { var toEncryptBytes

我一直在做一些关于在C#中使用AESCryptServiceProvider的研究。到目前为止,我有一个实现,它似乎正在工作。然而,我对初始化向量的理解是,当有效负载和密钥相同时,它应该保护我的密文不被相同,但似乎我做错了什么。更改初始化向量似乎根本不会影响这些函数的结果

以下是我的职能:

public string EncryptString(string toEncrypt, byte[] encryptionKey, byte[] iv)
{
    var toEncryptBytes = Encoding.Default.GetBytes(toEncrypt);
    using (var aes = new AesCryptoServiceProvider())
    {
        aes.Key = encryptionKey;
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.PKCS7;
        //aes.GenerateIV();
        aes.IV = iv;

        using (var encryptor = aes.CreateEncryptor(encryptionKey, aes.IV))
        using (var ms = new MemoryStream())
        {
            using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
            using (var bWriter = new BinaryWriter(cs))
            {
                bWriter.Write(aes.IV, 0, aes.IV.Length);
                bWriter.Write(toEncryptBytes, 0, toEncryptBytes.Length);
                cs.FlushFinalBlock();
            }
            return Convert.ToBase64String(ms.ToArray());
        }
    }
}

public string DecryptString(string toDecrypt, byte[] encryptionKey, byte[] iv)
{
    using (var aes = new AesCryptoServiceProvider())
    {
        aes.Key = encryptionKey;
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.PKCS7;
        var toDecryptBytes = Convert.FromBase64String(toDecrypt);

        Array.Copy(toDecryptBytes, 0, iv, 0, iv.Length);
        aes.IV = iv;

        using (var ms = new MemoryStream())
        {
             using (var cs = new CryptoStream(ms, aes.CreateDecryptor(aes.Key, iv), CryptoStreamMode.Write))
             using (var binWriter = new BinaryWriter(cs))
             {
                 binWriter.Write(toDecryptBytes, iv.Length, toDecryptBytes.Length - iv.Length);
             }
             return Encoding.Default.GetString(ms.ToArray());
        }
    }
}
我现在按照@owlstead的建议更新了加密函数的新版本,更改回CBC模式。现在使用CBC时,这似乎工作正常

public string EncryptString(string toEncrypt, byte[] encryptionKey)
{
    var toEncryptBytes = Encoding.Default.GetBytes(toEncrypt);
    using (var aes = new AesCryptoServiceProvider())
    {
        aes.Key = encryptionKey;
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.PKCS7;
        aes.GenerateIV();

        using (var encryptor = aes.CreateEncryptor(encryptionKey, aes.IV))
        using (var ms = new MemoryStream())
        {
             ms.Write(aes.IV, 0, aes.IV.Length);
             using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
             using (var bWriter = new BinaryWriter(cs))
             {
                 bWriter.Write(toEncryptBytes, 0, toEncryptBytes.Length);
                 cs.FlushFinalBlock();
             }
             return Convert.ToBase64String(ms.ToArray());
        }
    }
}

您将
CryptoStream
BinaryWriter
按错误的顺序放置,至少对于encrypt函数是这样。您当前正在加密您的IV,而IV应该放在密文前面,以明文形式


IV在加密前与纯文本异或。现在,这意味着您将纯文本归零:您正在加密一个零值块。

CipherMode.ECB模式似乎没有拾取IV参数(这意味着无论传入什么IV,结果都是相同的),这是可能的,因为ECB不需要一个概念作为初始向量,因为也没有后续向量。如果要屏蔽ECB块,请在加密前手动对块进行异或。
当您更改为CipherMode.CBC时,IV确实很重要,因为后续块将与以前的加密块异或,形成一个链。

“似乎根本不会影响这些函数的结果。”您的意思是相同的输入会产生相同的输出吗?不同的IV输入会产生相同的输出。例如,我使用密钥“aaabbcccdddtoigjaeoitgjioeajtga”和IV“aaabbcccdddtoi5”对一些数据进行加密。这将返回“WIZzTtGBynNs/lN7Yqs4Gb8hDHInW4fgpCTOWUifIwc=”作为密码文本。我用相同的密钥但不同的IV将其传递给我的解密方法,并获得了原始文本。另一点值得一提的是,在调用EncryptString函数时更改IV将生成相同的密文。首先,您对IV的选择是不必要的复杂,您可以只设置零数组的第一个字节。另外,如果您完全确定AES模块正常工作,并且您可能使用了错误的模块,那么可能您的IV始终是零,或者是调试。这不仅会随机设置我的IV字节数组的第一个字节,从而将其余字节保留为零,将使用相同密钥和相同明文的算法可能输出的数量减少到255?不,只需使用不同的IV,每次,无论IV是什么,只更改第一个字节会导致相同的值,这是正确的,但我要说的是,对于调试或启动IV,您不必太疯狂。例如,只需增加字节数,所有16个字节一次增加一个,然后将清除数据的长度放在前2个字节或其他位置。