对称加密(AES):与加密数据一起保存IV和Salt是否安全正确? [英] Symmetric Encryption (AES): Is saving the IV and Salt alongside the encrypted data safe and proper?

查看:176
本文介绍了对称加密(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;
使用(AesCryptoServiceProvider provider = new AesCryptoServiceProvider())
{
provider.GenerateIV();
provider.Key = CreateKey(password,provider.KeySize);
provider.Mode = CipherMode.CBC;
provider.Padding = PaddingMode.PKCS7;

使用(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 [] decryptptedData = new byte [data.Length];
使用(AesCryptoServiceProvider provider = new AesCryptoServiceProvider())
{
provider.Key = CreateKey(password,provider.KeySize);
provider.Mode = CipherMode.CBC;
provider.Padding = PaddingMode.PKCS7;
使用(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(decryptptedData,0,decryptptedData.Length);
}
}
}
}
return decryptptedData;
}

我也欢迎任何有关对称加密的其他信息。

解决方案

使用密文存储IV和Salt很长时间是适当的,也是最佳做法。硬编码盐是没有用的,随机是重要的,硬编码迭代是完全可以的,但通常远高于300(实际上至少1000,如果您的机器/使用可以处理它,通常会高出10秒因为我已经看到这么多坏的(或旧的)c#加密的例子从堆栈溢出切割并粘贴到开源代码中,我写了一个简短的(或几个)一些剪切和粘贴加密代码字符串对称认证加密的现代示例,我试图保持最新和审查。它将iv和salt与密文一起存储,它还验证密文中包含的密文和值。



理想情况下,最好的做法是使用高级加密图书馆会处理像你这样的最佳做法,但是通常对于csharp来说这些都不存在。我一直在使用谷歌的 keyczar 库。虽然它的功能准备使用,我一直想要在第一次官方稳定版本之前更多地关注代码。


I am trying to make sense of how to handle and manage an initilization vector and salt (when applicable) when encrypting and decrypting data using a symmetric encryption algorithm, in this case AES.

I have deduced from different SO threads and various other websites that neither the IV or salt need to be secret, only unique in order to defend against cryptanalytic attacks such as a brute-force attack. With this in mind I figured that it would be viable to store my pseudo random IV with the encrypted data. I am asking if the method I am using is proper and furthermore, should I be treating my currently hard coded salt in the same manner? That being writing it to the memory stream along side the IV

My code:

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;
}

I am also open to any other information about symmetric encryption with regards to proper practice.

解决方案

Storing the IV and Salt a long with the cipher text is proper and a best practice. Hard coding the salt is not useful, being random is important, hard coding the iterations is perfectly okay but is typically much higher than 300 (in fact at least 1000 and you typically go much higher if your machine/usage can handle it as in 10s of thousands).

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.

这篇关于对称加密(AES):与加密数据一起保存IV和Salt是否安全正确?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆