23

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

我从不同的 SO 线程和各种其他网站推断出,IV 或 salt 都不需要保密,只是为了防御诸如暴力攻击之类的密码分析攻击是唯一的。考虑到这一点,我认为将我的伪随机 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;
}

关于正确实践,我也愿意接受有关对称加密的任何其他信息。

4

2 回答 2

29

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

Because I've seen so many bad (or old) examples of c# encryption from stack overflow cut and paste into open source code, I wrote a short bit of cut and paste encryption code Modern Examples of Symmetric Authenticated Encryption of a string. that i try to keep up to date and reviewed. It stores the iv and salt with the ciphertext it also authenticates the ciphertext and values included with the cipher text.

Ideally though a better practice would be to use a high level encryption library that would handle best practices like the iv for you, however those typically haven't existed for csharp. I've been working on a native csharp version of google's keyczar library. While it's functionally ready for use, I've been wanting to get more eyes on the code before the first official stable release.

于 2012-12-17T14:01:32.770 回答
13

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

举个例子,看看rncryptor 数据格式。在这里,盐和 IV 与密文和 MAC 值一起打包成数据格式。(注意:这是一个objective-c 示例)。

于 2012-12-16T13:36:36.550 回答