我正在为数据库中的敏感数据编写加密序列。
目前我正在使用基于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来获取我想要的数据?
答案 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确保彩虹表攻击是不可能的,并且相同的密码(多个用户)不会导致相同的散列。
由于设计错误需要重复全部工作(如果需要多个哈希输出),建议不要从哈希函数的输出请求更多数据。在这种情况下,最好使用另一种方法来扩展输出密钥材料(字节),例如,香港民主促进会-展开。
对问题代码的观察:
GenerateHash
方法是虚假的,Rfc2898DeriveBytes
将为您执行此操作; 只是一般提示,只使用生成的密钥来加密由安全随机函数创建的数据特定密钥。然后你甚至不需要打扰IV,你可以通过解密数据特定密钥来“重新”,并使用新密钥对其进行加密。