【问题标题】:What does the output of Rfc2898DeriveBytes depend on and how should the salt be treated?Rfc2898DeriveBytes 的输出取决于什么,盐应该如何处理?
【发布时间】:2017-09-01 07:56:57
【问题描述】:
public string Encrypt(string Code)
{
    string result = string.Empty;
    byte[] encryptResult = null;
    var CodeInByte = Encoding.ASCII.GetBytes(Code);

    try
    {
        using (MemoryStream memo = new MemoryStream())
        {
            using (RijndaelManaged AES = new RijndaelManaged())
            {
                AES.KeySize = KeySize;
                AES.BlockSize = BlockSize;

                var key = new Rfc2898DeriveBytes(CodeInByte, salt, 1000);
                AES.Key = key.GetBytes(AES.KeySize / 8);
                AES.IV = key.GetBytes(AES.BlockSize / 8);

                AES.Mode = CipherMode.CBC;

                using (var encrypt = new CryptoStream(memo, AES.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    encrypt.Write(CodeInByte, 0, CodeInByte.Length);
                    encrypt.Close();
                }

                encryptResult = memo.ToArray();
            }
        }

        result = Convert.ToBase64String(encryptResult);
        return result;
    }
    catch (Exception err)
    {
        MsgCode = 99;
        MsgDesc = err.Message;
        return string.Empty;
    }            
}

这只是一个简单的字符串AES加密方法

我想问的一点,在生成密钥时,在

var key = new Rfc2898DeriveBytes(CodeInByte, salt, 1000);

key 是从输入的字符串生成的,还是只是随机生成的字节数组?

而且,盐是否需要是静态的

【问题讨论】:

  • key是由string和salt生成的,迭代次数也是影响结果和运行时间的算法参数。 salt 不需要是静态的,但如果您使用不同的 salt,您将获得不同的密钥,因此它在解密端需要与给定加密时相同。
  • 盐必须是随机的。不要使用静态盐,因为这会使密码具有确定性,因此在语义上不安全。观察密文的攻击者可以确定之前发送相同消息前缀的时间。盐不是秘密的,因此您可以将其与密文一起发送。通常,它只是简单地添加到密文中,并在解密之前被切掉。应该以与初始化向量 (IV) 完全相同的方式处理盐。

标签: c# cryptography salt pbkdf2


【解决方案1】:

正如documentation on MSDN 建议的那样:

Rfc2898DeriveBytes 接受密码、盐和迭代计数,然后通过调用 GetBytes 方法生成密钥。

换句话说,它将使用您给它的输入参数派生字节。如果你给它不同的参数,派生的密钥就会不同。如果你给它 same 参数,它将生成相同的字节。

对称加密算法(例如 AES)需要一个固定长度的密钥 - 在这种情况下 AES128 为 16 个字节。但是,您不想强制要求密码是固定长度的,因为这会使它们更容易受到攻击。您可能还需要比可行密码更长的密钥 - 例如,AES256 需要 32 字节的密钥。最后,密码往往是字母数字,可能有一些符号,而加密密钥由范围从 0x00-0xFF 的字节组成,如果你将加密密钥设置为 32 个字符的 ASCII 密码,那么你会缩小范围可打印的 ASCII 字符范围远小于 0x00-0xFF。

出于这个原因,您希望从给定的密码中派生加密密钥,从而获得所需长度的强密钥。这就是 Rfc2898DeriveBytes 的用武之地。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-14
    • 2020-09-14
    • 1970-01-01
    • 2021-10-04
    • 1970-01-01
    • 1970-01-01
    • 2014-10-15
    • 2020-08-11
    相关资源
    最近更新 更多