4

请密码学大师帮忙。

我了解到,使用对称算法(例如 AES)的加密密钥应该通过 PBKDF2 函数从密码中派生,在每次加密中使用随机盐。我还了解到 IV 不应该是硬编码的,也不应该直接绑定到(派生自)密码字符串或加密密钥。到目前为止,我一直随机生成密钥派生 saltIV,每个 16 个字节用于我的 AES-256 加密,并将它们与加密的有效负载一起存储。

现在我认为IV的随机生成是多余的,如果我使用随机盐,因为我可以使用该盐从密码字符串中导出密钥和IV。或者也许我不应该?

所以我的问题最终是这样的:

我可以从密码中导出初始化向量(就像我使用密钥一样),还是每次都应该生成随机 IV,因为我在每次加密中都使用随机盐?

那么我可以使用下面的 C# 代码吗?

// Derive key and initialization vector from password:

// ---> NOTE: _salt is random 16 bytes in each encryption.

byte[] key, iv;

using (Rfc2898DeriveBytes derivedBytes = new Rfc2898DeriveBytes(password, _salt, _iterations))
{
    key = derivedBytes.GetBytes(32);
    iv = derivedBytes.GetBytes(16);
}
4

4 回答 4

4

是的,您可以这样使用它,只要您永远不会对相同的密码(即使在时间上)使用相同的盐来计算密钥和 IV。仅当您使用相同的密钥进行加密时,IV 才必须是唯一的,并且您每次都会计算一个新的密钥。原则上,您甚至可以使用全零 IV,因为密钥从不重复,但最好使用派生的。

请注意,如果您的一位同事认为PasswordDeriveBytes- Microsoft PBKDF1 的错误实现 - 更适合该任务,那么您很可能容易受到各种攻击。这只是一个示例,如果您的安全边际很紧,可能会出现问题......

当然应该首选完全随机的 IV。

于 2012-09-27T22:46:06.413 回答
0

你是什​​么意思“在每次加密中使用随机盐”?最好随机派生 salt 和 IV,例如密码学标准随机数生成器的输出,并将其与派生字节一起存储。为每个密码生成一个新的 IV 和盐。

为什么来自密码学标准 RNG?从密码派生意味着派生字节函数中的任何弱点都反映在字节和 IV 中。在现代编程语言中,从 RNG 生成它并不难,并且使用 RNG 可确保加密的新密码的 IV 不可预测。可能有更好的理由,但我正在画一个空白。

于 2012-09-27T11:32:13.870 回答
0

任何加密系统的不同部分之间的链接越多,任何攻击者就越容易将这些链接用作从系统的一个部分到另一个部分的后门。请记住,IV 是明文发送的,而密钥必须保密,因此它们之间的任何形式的链接都是巨大的风险。

用于Rfc2898DeriveBytes生成您的密钥并使用良好的加密 RNG 生成 IV。请记住,攻击者会看到 IV,因此无需执行完整的 RFC 2898 流程。对 IV 使用标准加密 RNG,它可能比 RFC 2898 过程更快,因为它没有迭代。

于 2012-09-27T11:45:21.867 回答
0

使用 AES-CBC 时初始化向量的语义安全性最重要的部分是它不应该是可预测的。

通过您建议的实现,给定的密钥将始终具有相同的初始化向量,但由于您的 128 位盐,您不会使用相同的密钥。看起来很不可预测,也就是说,这不是一个最佳实践,而且通常当你做一些聪明的事情来节省 16 个字节的空间时,你会失去某种安全性,或者让自己面临一些未知的攻击向量。

我认为您应该使用 RNG 并占用 16 字节的空间,在处理加密时保守是游戏的名称。您可能还应该研究其他内容,例如经过身份验证的加密,我在 codereview 上有一个示例实现

最终,还有其他重要的事情会为安全性提供超出 iv 的额外开销,例如身份验证加密、版本控制和密钥轮换,而且实际上还没有任何用于 C# 的高级加密框架。我一直在研究 Google 的Keyczar框架的 C# 实现。如果您愿意,可以在 github Keyczar-dotnet上关注它。它的功能非常完整,并且具有 90% 的测试覆盖率,但保守地说,在它被正式接受为项目的一部分之前,我不建议使用它,并且将来可能会有更多人关注它。

于 2012-09-27T14:21:45.353 回答