使用派生密钥/IV 的 AES。它会引入弱点吗?

信息安全 加密 密码学 Web应用程序 密钥管理 AES
2021-08-26 11:32:35

我正在寻找一种有效的方法来使用 AES 加密数据库中的多个字段,使用单个全局密钥,在整个大型 Web 应用程序中使用。

显然,为了重用这个密钥,每个要加密的字段都需要一个唯一的随机 IV。

我宁愿不向数据库引入更多字段来存储这些 IV 中的每一个,因此编程方法似乎是以某种方式派生这些 IV。

我正在玩弄使用以下任何一种:

key = sha256(global_key + table_name)
iv = sha256(column_name + primary_key)

甚至简单地说:

key = global_key
iv = sha256(table_name + column_name + primary_key)

我倾向于前者来生成每个表的键。

已经读过IV不需要保密。因此,我正在假设派生密钥或 IV(即使算法已知)并不比任何其他非秘密 IV 更不安全,只要原始密钥仍然是 secret

问题是:

我的方法有致命缺陷吗?我是否引入了任何严重的弱点,如果对手获得数据库的副本,会使他们更容易检索明文数据?

我意识到这可能会征求一个词的答案。

非常欢迎对替代/更好方案的建议,以及对现有作品的参考以及它们如何实现类似场景。

3个回答

一种可能更好的方法是将 IV 和密文存储在一个列中。这样,您可以以最适合您选择的加密模式的方式生成 IV,同时也不必添加列。

类似于"$AES-128-CBC$" + Base64.encode64(iv) + "$" + Base64.encode64(ciphertext)中使用的格式crypt,易于解析,并且使用 Base64 编码在使用命令行客户端对数据库进行查询时稍微方便一些。

你的方法是不安全的。如果您修改数据库中的某些值,您将使用与加密先前值相同的 IV 来加密新值。(数据将存储在同一位置,因此表名、列名和主键将保持不变。)这可能会损害机密性。如果您使用流密码或 AES-CTR 或类似模式,这种妥协尤其糟糕,因为您使用相同的流加密了两个不同的值,这是一个经典的密钥流重用漏洞(两次密码非常不安全) .

相反,最好按照其他人的建议:生成一个随机IV,并将其与密文一起存储。实际上,在大多数操作模式中,您可以将 IV 视为密文的一部分。

我假设您使用的是CBC模式...

我会提出这是违反 CWE-329的论点。 IV 可以被攻击者知道,但它必须是随机的。解决您的问题的一个更常见的方法是存储一个非常安全的随机值并将其用作您的“IV”。

假设您有一个名为“secret”的表。攻击者有一个 SQL 注入漏洞,看到这个表,他也可以看到当前主键的值。通过计算一个简单的 sha256 哈希,他能够预测下一个 IV,甚至可以按计算未来 IV 的表。(根据您的平台,SQL 注入漏洞可能会变成解密预言机!讨厌!)

如果我在哪里构建它,我将使用适当的密钥派生函数,例如 PBKDF2。这些是较重的函数,使攻击者更难进行矿石计算或大规模计算。它不必重得多,但结果值必须与您的密码大小相同。

另一种可能的解决方案是拥有一个全局“IV 机密”。传递iv_secret + column_name + primary_key给您的密钥派生函数以生成您的 IV。由于使用了秘密,IV 不再是可预测的值,这不再是 CWE-329 违规。此外,这个值也是一个随机数,不太可能为两个不同的值生成两次相同的 IV...(除非您进行了更新,否则将违反)。为了缓解这种情况,您可以在 IV 计算中添加“版本号”或最后修改的时间戳。