使用 Rijndael 加密时的密钥、盐和 IV

Key, salt and IV when using Rijndael encryption

我正在开发一个用户可以上传文件的网站。我想加密这些文件,以防在授予它们访问权限时出现某种安全漏洞。

当用户想要下载他们的文件时,我直接解密到 HTTP(S) 输出流。

文件放在光盘上,每个文件的记录都与一些附加数据(文件名、大小、文件路径、IV 等)一起插入网站数据库。

我对如何使用加密只有基本的了解,因此有一些问题。

我正在使用 Rfc2898DeriveBytes 生成加密密钥的字节。用这个class可以吗?据我所知它使用 SHA1,它可能不再安全?

现在我对每次加密都使用相同的密码和盐,但每次都是随机 IV。我是否也应该随机化盐并将其与 IV 一起保存在数据库中?这会提供额外的安全性吗?

我应该使用消息验证码 (MAC) 吗?加密后的文件本身只存储不传输,不知道有没有必要

我真的不知道如何最好地存储加密密码。我不想将它包含在我的网站 DLL 中,所以我可能会将它放在服务器上某个不在我的网站文件夹中的文件中。我还能怎么做?

这是我的加密代码。是否存在明显的安全漏洞?

const int bufferSize = 1024 * 128;

Guid guid = Guid.NewGuid();
string encryptedFilePath = Path.Combine(FILE_PATH, guid.ToString());
byte[] rgbIV;

using (Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes("PASSWORD HERE", Encoding.ASCII.GetBytes("SALT HERE")))
{
    byte[] rgbKey = deriveBytes.GetBytes(256 / 8);

    using (FileStream decryptedFileStream = File.OpenRead(decryptedFilePath))
    using (FileStream encryptedFileStream = File.OpenWrite(encryptedFilePath))
    using (RijndaelManaged algorithm = new RijndaelManaged() { KeySize = 256, BlockSize = 128, Mode = CipherMode.CBC, Padding = PaddingMode.ISO10126 })
    {
        algorithm.GenerateIV();
        rgbIV = algorithm.IV;

        using (ICryptoTransform encryptor = algorithm.CreateEncryptor(rgbKey, rgbIV))
        using (CryptoStream cryptoStream = new CryptoStream(encryptedFileStream, encryptor, CryptoStreamMode.Write))
        {
            int read;
            byte[] buffer = new byte[bufferSize];
            while ((read = decryptedFileStream.Read(buffer, 0, bufferSize)) > 0)
                cryptoStream.Write(buffer, 0, read);
            cryptoStream.FlushFinalBlock();
        }
    }
}

I'm using Rfc2898DeriveBytes to generate the bytes for the encryption key. Is it okay to use this class? As far as I know it uses SHA1, which might no longer be secure?

最近 SHA-1 的有效破坏实际上只影响 PBKDF2(Rfc2898DeriveBytes 背后的算法)不需要的抗碰撞性。参见:Is PBKDF2-HMAC-SHA1 really broken?

Right now I'm using the same password and salt for each encryption, but a random IV each time. Should I also be randomizing the salt and keep it in the database along with the IV? Will this give additional security?

也许它会提供额外的安全性,但这样做肯定不会有什么坏处,除非你添加了一个错误。资料来源:Need for salt with IV

Should I be using a message authentication code (MAC)? The encrypted files themselves are only stored and never transferred, so I don't know if it's necessary.

通常,存储系统有检查和程序来防止和修复数据损坏。如果没有,那么 MAC 是检查数据是否损坏的好方法,即使这不是恶意发生的。

如果最终用户应该接收到数据,他们可以自己检查 MAC 并确保没有人更改密文。

I don't really know how to best store the encryption password. I don't want to include it in my website DLL, so I'll probably have it in a file on the server somewhere that isn't in my website folder. How else could I be doing this?

据我了解,您实际上想要按住 encryption/decryption 键。您可以做的任何事情实际上都是混淆视听,并不能提供任何实际的安全性。攻击者可能只是使用与您常用代码相同的数据存储连接。充其量,攻击者的速度会慢一点。在最坏的情况下,他们甚至不会注意到数据已加密,因为解密是透明进行的。

最好确保攻击者无法进入。查看 OWASP 前 10 名并尝试遵循建议。然后你可以使用 Nikto 进行一些安全扫描或聘请专业的渗透测试人员。

This is my code for encryption. Any obvious security flaws?

使用 PaddingMode.ISO10126 似乎不是个好主意。您应该使用 PKCS#7 填充。资料来源:Why was ISO10126 Padding Withdrawn?

  1. Rfc2898DeriveBytes 本质上是 NIST 推荐的 PBKDF2。

  2. 如果您将盐随机化(一种良好的安全做法),将有顶级供应它用于解密。一种常见的方法是在加密数据前加上salt和IV。

  3. 是的,您应该对加密数据和上述任何前置信息使用 Mac。

  4. 为了提供有关保护加密密钥的建议,请提供有关如何使用加密的更多信息。

  5. 使用 PKCS#7 填充,有时由于历史原因该选项被命名为 PKCS#5。