如何安全地将“字符串”密码转换为 AES 中使用的密钥?

信息安全 密钥管理 AES
2021-09-02 00:19:50

我正在编写一些软件,我必须使用 AES 加密写入特定文件夹的所有文件。在某处配置了一个密码/密钥,始终使用该密码/密钥。

我不想存储 base64 字符串,因为这对于可能不得不更改配置的人来说太复杂了。我想存储一个包含任何字符的字符串。将此密码转换为用于 AES 的密钥的最佳方法是什么?

  • 我可以从密钥中获取字节吗?
  • 我应该使用 PBKDF2 生成密钥吗?

据我了解,我还需要提供盐。但是,在我的情况下,盐似乎没有必要,因为我只有一把钥匙。

  • 我只是提供空盐还是不安全?
  • 还是有完全不同(希望更简单)的方式?
3个回答

您所做的是以下内容:

  • 生成长密钥(这只是一个安全的随机生成量数据,可以使用128位)
  • 您使用此密钥使用 AES 加密您的文件(这意味着您将其用作密码)
  • 您使用密码使用 AES 加密密钥本身(这有点短但更容易记住。现在 AES 再次要求它的长度为 128、192 或 256 位,因此您需要设置该长度的密码。因此,您可以只使用 PBKDF2(或 scrypt 或 bcrypt)从您的密码创建一个固定长度的密钥。 不要存储这个
  • 您使用 PBKDF2(或 bcrypt 或 scrypt)保留哈希密码的哈希值。这将允许您在尝试解密加密密钥之前检查密码是否正确。

所以:

hash(hash(password)) --> can be stored
hash(password) --> cannot be stored

即使您只有一个键,您也总是需要提供盐(这在很大程度上防止了彩虹表查找)。幸运的是,盐的生成是由 PBKDF2 自动完成的。

所以最后你实际上有3件事:

  • 您的加密文件
  • 您的加密密钥
  • 用于验证密码的哈希值

您可能会问为什么需要密钥:如果您要更改密码(并且您已使用密码加密了所有文件),您需要先使用原始密码解密所有文件,然后使用新密码重新加密它们密码。使用此实现,您需要做的就是解密并重新加密密钥(因为此密钥用作您的密码)。

编辑

我有点误解了你的问题,我添加了密钥推导函数。

也是一本好书(IBM 提供)

要将密码转换为 AES 密钥,PBKDF2是处理它的最简单方法。只要确保密码有足够的

确实需要使用盐,因为它可以防止彩虹表攻击。

根据您的平台,可能已经有可用的库来帮助解决此问题。如果没有,我会推荐一些接近 Lucus Kaufman 解决方案的东西。

设置:

  1. 生成一个随机 128 位密钥 (k1)、一个随机 128 位IV和一个随机(64 位可能就足够了)。
  2. 使用PBKDF2从您的密码和 salt 生成一个 256 位密钥,然后将其拆分为两个 128 位密钥(k2、k3)。
    • 确保您的算法的本机输出至少为 256 位,否则会很慢。PBKDF2- SHA256是一个不错的选择。不要为此使用两个单独的算法,因为它只会让你变得更慢和更复杂,但不会减慢攻击者的速度。
    • 如果您的密码已经具有足够高的熵,那么您可以使用相当少的迭代次数。1000 次迭代将如此之快,您甚至都不会注意到它(特别是因为您只需要在程序启动时解密密钥),因此没有太多理由低于此值。如果您的密码较弱,您可以提高迭代次数以进行补偿。
    • 我不建议为此使用bcrypt,因为它的输出大小错误,您需要再次对其进行哈希处理,这会增加不必要的复杂性。
    • 我认为scrypt可以生成任意大小的输出,因此如果它可用,这将是一个不错的选择(如果您想要FIPS合规性,这可能是不允许的)。
  3. 使用 k2使用随机 IV 对 k1 进行AES加密。
  4. 将加密的密钥、k3、salt 和 IV 保存到某个文件中。

加密/解密:

  1. 使用 PBKDF2 + 您的密码和文件中的 salt 来重新生成 k2 和 k3。
  2. 验证 k3。如果不匹配,则可能是您的密码错误,或者有人篡改了您的文件。停在这里。
  3. 使用文件中的 k2 和 IV 来解密 k1。
  4. 使用 k1 加密或解密文件。

密码更改

  1. 解密 k1,如加密/解密部分。
  2. 按照Setup中的步骤,使用相同的 k1,但重新生成其他所有内容(新的随机盐和 IV,从新密码生成 k2 和 k3)。

不要将 k2 存储在任何地方。不要存储未加密的 k1。做这些事情中的任何一个都会破坏系统的安全性。

如果您不关心能够更改密码(我认为这是一个非常重要的功能,但也许您不关心),那么您可以跳过涉及 k1 的步骤,并使用 k2 作为您的 AES 密钥和 k3验证它。

您可能还会发现为HMAC生成另一个密钥很有用,因此您可以验证加密文件没有被篡改。如果您想这样做,您可以生成一个 128 位 HMAC 密钥,并使用主 AES 密钥对其进行加密和存储。

如果您生成一个密钥,您应该以某种方式对其进行散列,考虑到散列函数是“有点像”伪 rng。所以使用 PBKDF2 总是好的,因为它是一种密钥派生方法并且专门用于此目的。你传入一个密码,它会根据你的密码和盐生成一个你可以使用的密钥。至于 Salt,它自动成为 PBKDF2 的一部分,因此您不必担心它。

如果您使用 .NET 之类的东西并将密钥存储在 web.config 文件中,您可以使用机器密钥或 RSA 密钥http://msdn.microsoft.com/en-us/library加密 web.config 的部分内容/dtkwfdky%28v=vs.100%29.aspx ,这样做的好处是 Windows 将负责存储 RSA 密钥和/或机器密钥。您甚至可以使用构建服务器自动执行此过程。