c# - 良好的 AES 初始化向量实践

标签 c# initialization-vector aescryptoserviceprovider

根据我的问题 Aes Encryption... missing an important piece ,我现在了解到我对字符串创建可逆加密的假设有点不对。我现在有

    public static byte[] EncryptString(string toEncrypt, byte[] encryptionKey)
    {
        var toEncryptBytes = Encoding.UTF8.GetBytes(toEncrypt);
        using (var provider = new AesCryptoServiceProvider())
        {
            provider.Key = encryptionKey;
            provider.Mode = CipherMode.CBC;
            provider.Padding = PaddingMode.PKCS7;
            using (var encryptor = provider.CreateEncryptor(provider.Key, provider.IV))
            {
                using (var ms = new MemoryStream())
                {
                    using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                    {
                        cs.Write(toEncryptBytes, 0, toEncryptBytes.Length);
                        cs.FlushFinalBlock();
                    }
                    return ms.ToArray();
                }
            }
        }
    }

这会产生一致的结果;但是,如果不知道/设置初始化向量,我将无法解密。我真的不想将三个值传递给此方法(在 IV 上),这让我不得不对 IV 进行硬编码或从 key 派生它。我想知道这是否是一种好的做法,或者它是否会使加密值容易受到某种方式的攻击……或者我真的想多了,应该只对 IV 进行硬编码吗?

更新 根据 Iridium 的建议,我尝试了这样的事情:

    public static byte[] EncryptString(string toEncrypt, byte[] encryptionKey)
    {
        if (string.IsNullOrEmpty(toEncrypt)) throw new ArgumentException("toEncrypt");
        if (encryptionKey == null || encryptionKey.Length == 0) throw new ArgumentException("encryptionKey");
        var toEncryptBytes = Encoding.UTF8.GetBytes(toEncrypt);
        using (var provider = new AesCryptoServiceProvider())
        {
            provider.Key = encryptionKey;
            provider.Mode = CipherMode.CBC;
            provider.Padding = PaddingMode.PKCS7;
            using (var encryptor = provider.CreateEncryptor(provider.Key, provider.IV))
            {
                using (var ms = new MemoryStream())
                {
                    ms.Write(provider.IV, 0, 16);
                    using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                    {
                        cs.Write(toEncryptBytes, 0, toEncryptBytes.Length);
                        cs.FlushFinalBlock();
                    }
                    return ms.ToArray();
                }
            }
        }
    }

    public static string DecryptString(byte[] encryptedString, byte[] encryptionKey)
    {
        using (var provider = new AesCryptoServiceProvider())
        {
            provider.Key = encryptionKey;
            provider.Mode = CipherMode.CBC;
            provider.Padding = PaddingMode.PKCS7;
            using (var ms = new MemoryStream(encryptedString))
            {
                byte[] buffer;
                ms.Read(buffer, 0, 16);
                provider.IV = buffer;
                using (var decryptor = provider.CreateDecryptor(provider.Key, provider.IV))
                {
                    using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
                    {
                        byte[] decrypted = new byte[encryptedString.Length];
                        var byteCount = cs.Read(decrypted, 0, encryptedString.Length);
                        return Encoding.UTF8.GetString(decrypted, 0, byteCount);
                    }
                }
            }
        }
    }

然而,这在我的单元测试中显示出一些奇怪的东西:

    [TestMethod]
    public void EncryptionClosedLoopTest()
    {
        var roundtrip = "This is the data I am encrypting.  There are many like it but this is my encryption.";
        var encrypted = Encryption.EncryptString(roundtrip, encryptionKey);
        var decrypted = Encryption.DecryptString(encrypted, encryptionKey);
        Assert.IsTrue(roundtrip == decrypted);
    }

我的解密文本显示为“92ʪ�F”�,hpv0� 我正在加密。有很多类似的,但这是我的加密。”这似乎几乎是正确的,但当然是完全错误的。不过看起来我很接近。我是否缺少内存流上的偏移量?

最佳答案

对于您的加密方法的每次运行,IV 应该是随机且唯一的。从 key /消息或硬编码派生它不够安全。 IV 可以在此方法中生成,而不是传递给它,并在加密数据之前写入输出流。

解密时,可以在加密数据之前从输入中读取 IV。

关于c# - 良好的 AES 初始化向量实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8041451/

相关文章:

c# - ArgumentException 多个参数和嵌套参数的 ParamName 约定

encryption - 为什么 golang 加密示例不使用随机 IV?

c# - System.PlatformNotSupportedException AesCryptoServiceProvider

ios - 无法在 iOS 中解密 AES128

c# - 使用 PST/CEST/UTC/等形式的时区解析 DateTime

c# - 具有多个允许值类型的数据库字段

c# - 将 varchar 值 '@a' 转换为数据类型 int 时转换失败

java - Initial Vector的CTR模式使用(四)

python - 在 Python 中使用 CBC 初始化向量显示(二进制)

java - AES128算法如何生成64位加密 key ?