标准 Java 6 使用什么基于密码的加密?

信息安全 应用安全 加密 密码 爪哇
2021-09-04 16:43:34

我应该在 Java 6 中使用哪种基于密码的加密方法?它应该尽可能强大,但可以使用默认的安全策略文件(不是您必须单独下载和安装的导出限制文件)?

2个回答

我的建议:你应该尽量避免使用基于密码的加密,如果你可以避免的话。特别是,在实践中,基于密码的加密往往是不安全的。问题是用户的密码很少有足够的熵来抵抗字典攻击。因此,如果您需要加密,您可能不想使用基于密码的加密,如果有其他选择的话。

更好的解决方案是给用户一个密钥,并使用该密钥进行加密或解密。

如果您不遵循我的建议:如果您绝对必须使用基于密码的加密,这里有一些建议可以在一定程度上降低风险:

  • 使用PBKDF2从密码中派生密钥。选择适当大量的迭代,以便密钥派生过程在用户机器上花费例如 100 毫秒。这将使对用户密码执行字典搜索变得更加困难——但是,它并没有消除风险,因此用户仍然必须付出额外的努力来选择一个很长的密码。

  • 尽你所能增加用户使用很长密码的可能性。最好的方法是自动为他们生成密码。我建议选择一个熵为 80 位的。如果您将其转换为使用 A-Za-z0-9(但不是 O 或 l,以避免与 0 或 1 混淆)的密码,则生成的密码将是 14 个字符长。用户可能不喜欢处理这么长的密码,但如果他们想要安全的话,他们只需要接受并处理。

    如果您让用户选择自己的密码,大多数人可能会选择质量较低的密码。我建议您包括有关风险的可怕警告。您应该建议他们选择至少 20 个字符长的密码,并且尽可能随机。您可能想提供一个小应用程序来为他们生成示例密码,他们可以剪切和粘贴并使用。

    即使您尽了最大的努力,如果用户选择自己的密码,许多用户可能会选择一个不够安全的密码。问题是加密需要的密码短语比您用于 Web 帐户密码的密码更长、更强。大多数用户可能不知道这一点,无论如何选择足够长且足够强大的密码短语的烦恼可能会阻止许多用户这样做并导致他们的行为不安全。

如果您觉得基于密码的加密很难安全使用,那么您的感觉绝对准确。

首先阅读@DW 的答案,里面充满了很好的建议。然后,如果您仍想进行基于密码的加密,请考虑以下事项:

  • 基于密码的加密是将密码转换为密钥,然后使用该密钥进行对称加密。
  • Java可以进行一些基于密码的加密,即在一个简化的 API 中完成这两个步骤,如下所示但是,它只允许密码散列机制和加密算法的某些组合,特别是,据报道不允许使用 AES,这是一个问题。
  • 没有什么能阻止您在代码中的两个单独步骤中进行密码到密钥的转换,然后进行加密。

请注意,密码散列机制通常不受密码法和出口法规的约束,因为它们不会“隐藏”数据。然后,我建议您在代码中只包含bcrypt的实现,例如jBCrypt,它是用 Java 编写的,具有简单许可的开放源代码,并且相当紧凑(一个源文件)。您需要稍微更改代码,因为该实现想要使用strings,而您想要原始位;因此,请执行以下操作:

  • 使用该crypt_raw()方法将密码和盐转换为 192 位 bcrypt 输出。
  • 使用 SHA-512 散列这 192 位(Java 6 包括 SHA-512 实现)。这产生 512 位。
  • 使用这些 512 位对数据进行 AES 加密,结果带有MAC(例如,使用 HMAC/SHA-256,然后再次受 Java 6 支持)。详情见下文。

(由于那里解释的原因我通常更喜欢 bcrypt 而不是 PBKDF2 ,但 PBKDF2 也不错,所以如果你真的想要 PBKDF2(或出于合规原因需要它),那就去吧。)

重要提示:正确地进行加密并添加 MAC,可能会以多种方式被破坏。强烈建议不要自己动手。但是,以下方法应该是安全的:

  • 您有 512 位“密码派生数据”。将其拆分为四个 128 位块。
  • 在 CBC 模式下使用 AES-128 加密数据。CBC 需要一个初始化向量,它是一个 16 个随机字节的数组。使用第一个 128 位块(来自 SHA-512 输出)作为密钥,第二个 128 位块作为 IV。此外,使用 PKCS#5 填充(因为您的输入数据的长度可能不是 16 的倍数)。
  • 加密完成后,在由 IV 组成的输入上计算 HMAC/SHA-256,然后按顺序加密结果HMAC 的密钥将是来自 SHA-512 输出的第三个 128 位块。
  • “加密文件”必须包含 bcrypt 的盐(128 位,也就是 16 字节)、AES/CBC 加密的输出和 HMAC 输出(256 位,也就是 32 字节)。
  • 对于解密,使用盐(来自加密文件)和密码重新计算 bcrypt,然后应用 SHA-512 来获取 HMAC 的加密密钥、IV 和密钥。验证 HMAC 值,如果正确,解密数据。

而且,请记住:从不、从不从不为两个加密实例重用盐值(无论它们是否使用相同的密码)。java.security.SecureRandom每次要加密文件时,请始终使用它来生成全新的随机盐。