从 Rfc2898DeriveBytes 生成 AES IV

问题描述 投票:0回答:4

我正在使用

Rfc2898DeriveBytes
生成
AES
键和
iv
。但是,我听说
iv
不应该依赖于密码。这就是我现在的做法:

byte[] salt = GenerateRandomBytes(32); // Generates 32 random bytes
using (Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(plainStrPassword, salt)) {
    byte[] aesKey = rfc.GetBytes(32); 
    byte[] iv = rfc.GetBytes(16);    // Should I do this or generate it randomly?
}

我的问题:从

iv
生成
Rfc2898DeriveBytes
是否可以(安全)?或者我应该使用
RNGCryptoServiceProvider
随机生成它?

c# security encryption aes
4个回答
5
投票

让我们看看你的代码;

byte[] salt = GenerateRandomBytes(32); // Generates 32 random bytes
using (Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(plainStrPassword, salt)) {
    byte[] aesKey = rfc.GetBytes(32); 
    byte[] iv = rfc.GetBytes(16);    // Should I do this or generate it randomly?
}
  • 随机盐 - 好
  • Rfc2898DeriveBytes 加盐;只要用户密码具有良好的强度,这就很好。派生密钥的强度(不是熵!)不能超过密码的强度。
  • 调用 GetBytes(32) 获取 Key - 很好,这就是预期的结果。
  • 调用 GetBytes(16) 获取 IV -

这也很好; 自从

重复调用该方法不会生成相同的密钥;相反,使用 cb 参数值 20 追加两次 GetBytes 方法调用相当于使用 cb 参数值 40 调用一次 GetBytes 方法。

对于每次加密,您可以通过调用

GetBytes(16)
继续获取新的 IV。当然,这是有限制的。 PKKDF2 标准限制输出
2^32-1 * hLen
,请参阅RFC 8018

输出一部分作为 IV 并保留一部分作为加密密钥并没有什么问题。已经有大量使用 PBKDF2 的密码方案,即使密码哈希和盐已知,也没有被破解。

如果您担心这不是一个好主意,那么您可以使用其中一个;

  • 生成两个盐并分别从密码中导出 IV 和加密密钥:
byte[] saltForKey = GenerateRandomBytes(32); // Generates 32 random bytes
using (Rfc2898DeriveBytes rfcKey = new Rfc2898DeriveBytes(plainStrPassword, saltForKey)) {
    byte[] aesKey = rfcKey.GetBytes(32);

byte[] saltForIV = GenerateRandomBytes(32); // Generates 32 random bytes
using (Rfc2898DeriveBytes rfcIV = new Rfc2898DeriveBytes(plainStrPassword, saltForIV)) { 
    byte[] iv = rfcIV.GetBytes(16);    // Should I do this or generate it randomly?
}
  • 生成随机Salt并导出加密密钥,然后生成随机IV
byte[] salt = GenerateRandomBytes(32); // Generates 32 random bytes for Salt
byte[] IV = GenerateRandomBytes(16); // Generates 16 random bytes of IV

using (Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(plainStrPassword, salt)) {
    byte[] aesKey = rfc.GetBytes(32); 
}

请注意,您没有定义加密模式。对于类似

的模式
  • CTR 模式、96 位随机数和 32 位计数器是常见的。为此,96 位随机数也可以由计数器/LFSR 生成。确保 (key,IV) 对永远不会出现。
  • CBC模式,nonce必须是随机且不可预测的。上面的内容就可以了。
  • 当然,您应该忘记这些并使用经过身份验证的加密模式,例如 AES-GCM、ChaCha20-Poly1305。如果您担心 IV 重用,请使用 AES-GCM-SIV,它只能泄漏您发送了相同的消息,而不会泄漏其他内容。 SIV模式仅慢两倍,因为它必须通过明文推导IV,然后执行加密。

1
投票

不,从派生密钥的同一来源派生 IV 并不安全。 IV 的存在使得相同的消息在相同的密钥下加密会产生不同的密文。

您应该使用加密安全的随机源(例如您确定的

RNGCryptoServiceProvider
)来导出 IV 并将其与密文一起传递(通常作为一个字节流添加到密文之前,或者在更结构化的文件中的单独字段中)格式)。


0
投票

许多密码算法都表示为迭代算法。例如,当在 CBC 模式下使用分组密码加密消息时,每个消息“块”首先与前一个加密块进行异或,然后对异或的结果进行加密。第一个块没有“前一个块”,因此我们必须提供一个传统的替代“第零块”,我们称之为“初始化向量”。一般来说,IV 是开始运行算法所需的任何数据,并且不是秘密的(如果它是秘密的,我们将其称为“密钥”,而不是 IV)。

IV 是任意常数,因此任何值都可以。确保您的加密器和解密器使用相同的值。欲了解更多信息,您可以参考这些链接:

https://crypto.stackexchange.com/questions/732/why-use-an-initialization-vector-iv

https://crypto.stackexchange.com/questions/3965/what-is-the-main-difference- Between-a-key-an-iv-and-a-nonce


0
投票

基于this MS Docs,可以使用

Rfc2898DeriveBytes
从密码生成iv。
Rfc2898DeriveBytes
是PBKDF2的实现,其目的是:基于密码的密钥派生功能。请参阅那里的示例。

PS:你应该使用

RNGCryptoServiceProvider
来生成盐。

© www.soinside.com 2019 - 2024. All rights reserved.