了解Rfc2898DeriveBytes的工作原理

时间:2012-08-22 20:16:40

标签: c# encryption

我正在为数据库中的敏感数据编写加密序列。

目前我正在使用基于UserId的GUID,并将其放入哈希。然后,我通过Rfc2898DeriveBytes运行哈希来获取Key和IV,我用它来使用Rijndael函数加密数据。

我的代码如下所示:

        var salt = new byte[] { 1, 2, 23, 234, 37, 48, 134, 63, 248, 4 };
        const int iterations = 1000;
        using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(GenerateHash("2525"), salt, iterations)) {
            _key = rfc2898DeriveBytes.GetBytes(32);
            _iv = rfc2898DeriveBytes.GetBytes(16);
        }

然后我传递_key和_iv来解密或加密数据。 我的目标是让每个用户始终可以通过每个会话访问其唯一密钥。话虽如此,什么可以随机化,仍然保持这个功能?我是否总是必须使用相同的盐和相同的IV来获取我想要的数据?

1 个答案:

答案 0 :(得分:3)

Rfc2898DeriveBytes是PBKDF2的一个实现。显然,RFC 2898是一个引用to the standard,其中定义了基于密码的密钥派生函数。请注意,该标准比KDF更广泛;它的完整标题是“PKCS#5:基于密码的密码学规范,版本2.0”。

PBKDF2是PKCS#5 v1的后继者,它定义了PBKDF / PBKDF1。只有在PBKDF2出现后才添加1。类PasswordDeriveBytes是PBKDF1的实现。它不应再被使用了,因为KDF都已经过时,但也因为微软搞砸了实施;它可能重复输出密钥材料,如果超过底层哈希的输出 - SHA-1那么20字节 - 被请求。

除KDF外,PBKDF2也用作密码散列函数,其中散列而不是密码存储在数据库中。这样就可以验证密码,而如果对手检索到数据,则无法轻易检索到密码。后续RFC 8018中描述了这一点,其中包含2.1版本的协议。

在内部,PBKDF2只是重复密码和盐的哈希函数。迭代计数是工作因素;它指定在计算一个哈希值之前你(和对手)需要做多少工作。 salt确保彩虹表攻击是不可能的,并且相同的密码(多个用户)不会导致相同的散列。

由于设计错误需要重复全部工作(如果需要多个哈希输出),建议不要从哈希函数的输出请求更多数据。在这种情况下,最好使用另一种方法来扩展输出密钥材料(字节),例如,香港民主促进会-展开。


对问题代码的观察:

  1. GenerateHash方法是虚假的,Rfc2898DeriveBytes将为您执行此操作;
  2. 您应该使用比UID更难预测的内容来创建密钥;数据不应该直接供攻击者使用,因为这将完全打败PBKDF2的目的;
  3. 如果你想使用同一组UID + salt +迭代进行多次加密,那么你应该生成一个随机的IV并将其添加到密文中,使非随机IV完全违背IV的目的; < / LI>
  4. 您可以更改salt以获取多个密钥,但是您必须通过PBKDF2函数进行每次加密。
  5. 只是一般提示,只使用生成的密钥来加密由安全随机函数创建的数据特定密钥。然后你甚至不需要打扰IV,你可以通过解密数据特定密钥来“重新”,并使用新密钥对其进行加密。