使用 AES 和 CBC 时,IV 可以是明文的哈希吗?

信息安全 应用安全 密码学 加密 数据库
2021-09-04 01:48:17

[原载于programmers.stackexchange.com,标题为:Can you encrypt with AES+CBC and search the encrypted data ]

基本上,我将使用具有密码块链接模式或密码反馈模式或输出反馈模式的高级加密标准(我还没有决定)。每种模式都需要一个初始化向量。问题是我想让加密的字符串像这样“可搜索”:

假设我有一个数据库表列表以及每个表的“显示名称”。从概念上讲,列表看起来像这样(我用 {xxx} 表示 xxx 的加密形式,而 [IVx] 表示初始化向量):

ENC_DISPLAY_NAME         | ENC_TABLE_NAME
------------------------ | -----------------
[IV1]{John's table}      | [IV2]{TABLE_3574}
[IV3]{Eric's list}       | [IV4]{TABLE_3100}
                         |
[IV5]{Darren's projects} | [IV6]{TABLE_2823}
[IV7]{Paul's contacts}   | [IV8]{TABLE_5843}

现在假设我想允许对 ENC_DISPLAY_NAME 进行搜索。(只需要平等搜索。)我需要有某种方法来了解我想要查找的显示名称上使用了什么初始化向量。

我认为我应该计算显示名称的 128 位散列(可能是 CRC),并将其用作 IV 来计算加密字符串。也就是说,如果我想存储“Darren 的项目”,我应该这样做:

AESKey key = ...;
String str = "Darren's projects";
CRCType crc = ComputeCRC(str);

BinaryString enc = crc.ToBinaryString ( ).Concat
    (EncryptWithAESandCBC(str, key, (IVType)crc));

INSERT INTO MY_TABLE(ENC_DISPLAY_NAME,ENC_TABLE_NAME) VALUES(enc, ...);

如果我想改为搜索字符串,请执行相同的步骤,除了最后一个,然后SELECT * FROM MY_TABLE WHERE ENC_DISPLAY_NAME=enc.

这个以前试过吗?是否存在任何(安全)风险?

[相关问题:在给定明文及其密文的情况下计算 AES 加密密钥?]

3个回答

就“均匀随机性”而言,在明文上计算的散列将具有 IV 的正确特征。这是用于加密安全散列函数而不是CRC。相反,类似于 SHA-256。对于密码学来说,CRC 绝对不够安全。

但是,IV 必须被解密的人知道,因此它必须与加密消息一起存储。如果 IV 是使用来自明文的散列函数计算的,则这允许对明文执行字典攻击(尝试可能的明文,直到找到与散列匹配的明文)。对于密码而言,击败字典攻击已经足够困难了,密码是安全且随机的;因此,对于像显示名称这样完全非随机的东西,您应该真正使用从适当安全的加密随机数生成器生成的 IV,而不是从明文计算的哈希值。它不会改变您的存储成本,因为无论如何都必须存储 IV,无论您如何生成它。

简短回答:IV 必须是随机的并以明文形式发送。

您必须小心不要泄漏有关哈希中纯文本的信息。不能才有可能得到与你的哈希的彩虹表的纯文本。因此,存储在配置文件而不是数据库中的盐值是有序的。

话虽如此,我建议这样做:

  • 使用随机 IV,像现在一样存储
  • 将明文数据的加盐哈希存储在另一列中
  • 搜索加盐哈希以检索随机 IV 和密文

因此,在您的示例中,您将拥有以下内容:

NC_DISPLAY_NAME                                            | ENC_TABLE_NAME
-----------------------------------------------------------+------------------
hash(salt+"Darren's projects"), [IV5]{Darren's projects}   | [IV6]{TABLE_2823}

当然,盐渍哈希并非没有风险。它低于你最初试图避免但仍然存在的东西。如果这种风险很高,您可以在 ECB 模式下加密纯文本哈希(使用另一个 AES 密钥)并搜索它。所以你的桌子看起来像这样:

NC_DISPLAY_NAME                                               | ENC_TABLE_NAME
--------------------------------------------------------------+------------------
{k1 hash("Darren's projects")}, [IV5]{k2 Darren's projects}   | [IV6]{TABLE_2823}

做散列给你熵(输入白化)相当于使用IV(但我没有数学能力来确认它)。加密为您提供了对彩虹表和字典的保护。

您知道,当暴力破解搜索索引比暴力破解随机 IV 加密的密文需要更长的时间时,您将在速度安全上进行权衡。

如果您要将内容的散列放在那里,请意识到您的加密只会为您提供另一个数据副本。如果您使用它的只是查找,那么您所需要的只是哈希(无论如何,除非发生冲突)。因此,任何根据其名称查找特定行的攻击者都可以在不知道密钥的情况下找到它,只需忽略数据的加密部分并仅查找他正在寻找的内容的哈希值。

现在,如果您使用的摘要是 HMAC,而不仅仅是 CRC 或哈希,那么您可能会没事。但请意识到您确实需要小心不要泄露其他信息。