我的AES初始化矢量似乎与C#中的AESCryptoServiceProvider无关

本文关键字:中的 AESCryptoServiceProvider 无关 AES 初始化 我的 | 更新日期: 2023-09-27 18:28:37

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

以下是我的功能:

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());
        }
    }
}

我的AES初始化矢量似乎与C#中的AESCryptoServiceProvider无关

至少对于加密函数,您将CryptoStreamBinaryWriter按错误的顺序放置。你目前正在加密你的IV,而IV应该放在密文前面,很明显。

IV在加密之前与纯文本进行异或运算。现在,这意味着您将纯文本清零:您正在加密一个零值块。

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