对称加密(AES):保存IV和Salt以及加密数据是否安全且正确?

在使用对称加密算法(在本例中为AES)加密和解密数据时,我试图理解如何处理和管理启动向量和盐(适用时)。

我从不同的SO线程和各种其他网站推断出,IV或盐都不需要保密,只是为了防御密码分析攻击,例如蛮力攻击。 考虑到这一点,我认为将伪随机IV与加密数据一起存储是可行的。 我问的是我使用的方法是否合适,而且,我是否应该以同样的方式处理我当前的硬编码盐? 那就是将它写在IV旁边的内存流中

我的代码:

private const ushort ITERATIONS = 300; private static readonly byte[] SALT = new byte[] { 0x26, 0xdc, 0xff, 0x00, 0xad, 0xed, 0x7a, 0xee, 0xc5, 0xfe, 0x07, 0xaf, 0x4d, 0x08, 0x22, 0x3c }; private static byte[] CreateKey(string password, int keySize) { DeriveBytes derivedKey = new Rfc2898DeriveBytes(password, SALT, ITERATIONS); return derivedKey.GetBytes(keySize >> 3); } public static byte[] Encrypt(byte[] data, string password) { byte[] encryptedData = null; using (AesCryptoServiceProvider provider = new AesCryptoServiceProvider()) { provider.GenerateIV(); provider.Key = CreateKey(password, provider.KeySize); provider.Mode = CipherMode.CBC; provider.Padding = PaddingMode.PKCS7; using (MemoryStream memStream = new MemoryStream(data.Length)) { memStream.Write(provider.IV, 0, 16); using (ICryptoTransform encryptor = provider.CreateEncryptor(provider.Key, provider.IV)) { using (CryptoStream cryptoStream = new CryptoStream(memStream, encryptor, CryptoStreamMode.Write)) { cryptoStream.Write(data, 0, data.Length); cryptoStream.FlushFinalBlock(); } } encryptedData = memStream.ToArray(); } } return encryptedData; } public static byte[] Decrypt(byte[] data, string password) { byte[] decryptedData = new byte[data.Length]; using (AesCryptoServiceProvider provider = new AesCryptoServiceProvider()) { provider.Key = CreateKey(password, provider.KeySize); provider.Mode = CipherMode.CBC; provider.Padding = PaddingMode.PKCS7; using (MemoryStream memStream = new MemoryStream(data)) { byte[] iv = new byte[16]; memStream.Read(iv, 0, 16); using (ICryptoTransform decryptor = provider.CreateDecryptor(provider.Key, iv)) { using (CryptoStream cryptoStream = new CryptoStream(memStream, decryptor, CryptoStreamMode.Read)) { cryptoStream.Read(decryptedData, 0, decryptedData.Length); } } } } return decryptedData; } 

我也对有关正确练习的对称加密的任何其他信息持开放态度。

将IV和Salt与密文一起存储是正确的,也是最佳实践。 硬编码盐是没有用的,随机是很重要的,硬编码迭代是完全可以的,但通常远高于300(事实上至少1000,如果您的机器/使用可以像10s一样处理它,通常会更高成千上万)。

因为我已经从堆栈溢出剪切并粘贴到开源代码中看到了很多不好(或旧)的c#加密示例,所以我写了一小段剪切和粘贴加密代码字符串的对称认证加密的现代示例。 我试图保持最新和审查。 它将iv和salt与密文一起存储,它还validation密文和密文中包含的值。

理想情况下,更好的做法是使用高级加密库来处理像iv这样的最佳实践,但csharp通常不存在。 我一直在研究google的keyczar库的原生csharp版本 。 虽然它在function上可以使用,但我一直希望在第一次正式发布之前更多地关注代码。

是的,IV和盐都是公共价值。 更重要的是确保这些是每个加密操作的随机值。

要在野外举例说明,请查看rncryptor数据格式 。 在这里,盐和IV被封装成数据格式,以及密文和MAC值。 (注意:这是一个客观的例子)。