使用用户提供的密码和初始化向量的 AES-256-CBC 有多安全

信息安全 加密 php openssl AES
2021-08-15 09:23:55

据我了解,IV 仅用作第一个块的前一个块。但是由于每个块都被以下使用,这增加了重要的安全性,因为提供了 IV 而不是基于密码。

因此,当用户同时提供两者时,我实现了一个登录系统,至少 8 个字符使用他们关心的任何字符,只要他们使用至少 3 种类型(大写、小写、数字、特殊、非 ASCII)。

但是现在有人告诉我,通过定义 IV,我削弱了加密,因为这会使密码变得毫无用处。

我没有完全理解他的解释。

我的代码如下所示:

$hash = openssl_encrypt($username, 'aes-256-cbc', $password, false, md5($iv, true));
  • 是的,我正在加密用户名
  • 密码和 IV 都是用户定义的
  • 是的,我要求他们提供两个密码
  • 我将 IV 包装在 RAW md5 中,以确保获得标准的 16 chr 长度

有人可以澄清以这种方式使用 IV 是否是一种好的做法,并且这个想法是否足够强大。

2个回答

我的怀疑是:你做错了™

这就是为什么我这么认为,从我的头顶:

  1. 保存密文的变量称为hash
  2. 您正在加密用户名。
  3. 这看起来像一个XY-Problem
  4. 您不会(显示您如何)从密码中获取openssl_encrypt password密钥(根据文档,密钥是密钥。因此,除非您从用户提供的密码中获取密钥,否则这是行不通的。)
  5. 您没有使用 CSPRNG来获取 AES-CBC 的 IV。

但是现在有人告诉我,通过定义 IV,我削弱了加密,因为这会使密码变得毫无用处。

那个人是对的。请参阅有关将 CSPRNG 与 AES-CBC 结合使用的有关加密的链接问题以了解更多信息。

首先,通常的警告:不要推出自己的加密货币,你很可能弄错了。

现在第二个警告:您似乎仅使用AES- CBC加密数据,这非常危险,您确实应该使用AES- GCM,因为 AES 的 CBC 操作模式不会阻止消息被修改,可能导致不良结果。

现在你的加密方案的大问题是:你没有引入外部随机性
CBC 模式需要一个不可预测的 IV,否则您很容易受到攻击。根据您使用的事实MD5(pw2),这个 IV不是不可预测的,因为大多数密码都是可预测的。更糟糕的是,IV 应该在加密中引入随机性,并使相同的明文被加密为不同的密文。然而,您的用户可能不会理解这一点,并且会在多个加密中重复使用他的一对密码,因此您很容易受到静态 IV 攻击。

还有几个小问题:

  1. 您不能确保密钥(又名$password)正好是 32 字节长(使用 AES-256 的要求)和(伪)随机(安全的正式要求),一旦用户选择密码,您可能会遇到问题超过 32 个字符。
  2. 您向用户询问两个密码,而实际上您可以只向他们询问一个并从中派生两个(确定性地)。
  3. 您不处理密码现在,如果密文泄露,我可以继续尝试暴力破解用户的密码,因为您没有部署任何应对密码猜测的措施(例如使用bcrypt)。

那么,如何解决呢?

  1. 使用带有 12 字节随机数的 AES-GCM。
  2. 使用 OpenSSLs RNG 生成所述随机数。
  3. 安全地从用户密码导出 AES-GCM 密钥(即使用 bcrypt 或Argon2