【问题标题】:AES 256 bit encryption with Rfc2898DeriveBytes使用 Rfc2898DeriveBytes 的 AES 256 位加密
【发布时间】:2017-09-22 15:05:22
【问题描述】:

我在使用 AES 和 Rfc2898DeriveBytes 时遇到了困惑。这是我找到的代码......

public static string Decrypt(string encryptionKey, string cipherValue)
    {
        byte[] cipherBytes = Convert.FromBase64String(cipherValue);
        using (var encryptor = Aes.Create())
        {
            var pdb = new Rfc2898DeriveBytes(encryptionKey, new byte[] { (13 element byte array) });
            if (encryptor != null)
            {
                encryptor.Key = pdb.GetBytes(32);
                encryptor.IV = pdb.GetBytes(16);
                using (var ms = new MemoryStream())
                {
                    using (var cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(cipherBytes, 0, cipherBytes.Length);
                        cs.Close();
                    }
                    cipherValue = Encoding.Unicode.GetString(ms.ToArray());
                }
            }
        }
        return cipherValue;
    }

所以,“cipherValue”是一个加密字符串......以及“encryptionKey”。如何使用 AES 和 Rfc2898Derive 字节的其他示例似乎不适合此代码。我见过的其他示例使用纯文本代替上面的“encryptionKey”参数,但这些示例通常演示的是加密而不是解密。

此代码用于解密我的应用程序配置文件中的密码。加密已经完成,我没有可用资源告诉我它是如何完成的。我假设密码是使用指定的“encryptionKey”和盐值加密的,以及默认的 1000 次迭代和最大大小的密钥和 IV。

我主要对“encryptionKey”参数如何影响事物感到好奇。 “cipherValue”是被解密的内容,并给了我正确的输出。这里采用了什么方法,与我见过的其他示例相比,它有什么优势(如果有的话)?

加密和安全性还不是我的强项...如果我遗漏了任何可能更清楚地说明这一点的重要内容,请告诉我。提前致谢!

【问题讨论】:

  • 必须随机选择盐(Rfc2898DeriveBytes 的第二个参数)。不要使用静态盐,因为这会使密码具有确定性,因此在语义上不安全。观察密文的攻击者可以确定之前发送相同消息前缀的时间。盐不是秘密的,因此您可以将其与密文一起发送。通常,它只是简单地添加到密文中,并在解密之前被切掉。

标签: c# encryption cryptography aes rfc2898


【解决方案1】:

RFC2898DeriveBytesPBKDF2 的一个名称不佳的实现,它在 RFC 2898 中定义。(其名称不佳的部分原因是 RFC 2898 还描述了 PBKDF1 算法,这是 PasswordDeriveBytes 使用的)

您可以阅读链接的 RFC 部分中的完整算法,但它的作用是将密码用作 HMAC 密钥,然后获取盐的 HMAC 和一些状态数据,然后获取该 HMAC,然后其中,高达iterations HMAC。

目的是获取输入密码(低熵),并以一种难以弄清楚原始密码是什么的方式可预测地将其转换为加密密钥(高熵)。

只要所有输入都相同,它就会产生相同的答案。但是稍微改变任何输入都会产生截然不同的答案。

如果您看到的其他方法仅通过使用 Encoding.UTF8.GetBytes()(或类似方法)将密码转换为密钥,那么是的:这是一种更好的方法(它更难破解,而且它没有不在乎你的密码有多长)。

【讨论】:

    猜你喜欢
    • 2015-04-10
    • 1970-01-01
    • 2013-08-24
    • 1970-01-01
    • 1970-01-01
    • 2010-11-02
    • 1970-01-01
    • 2016-11-14
    • 1970-01-01
    相关资源
    最近更新 更多