用于可搜索加密的 Ciphersweet 库的安全性如何,为什么重复条目泄漏不是问题?

信息安全 加密 hmac 可搜索加密
2021-09-04 05:15:18

我目前正在管理一个代码库,其中我们有一个 mysql 数据库,其中所有记录都使用php-encryption library 加密这适用于我们当前的设置。我们现在有了一个新的业务需求,它应该可以SELECT基于其中一个加密字段进行操作。

由于无法根据加密值进行选择,因此我四处搜索并找到了 ciphersweet这是一个新的(6 个月大)回购,目前只有 136 个 github 星。我已经阅读了 lib 背后的公司写的一篇关于它的博文。

该想法基于盲索引,其中一般想法是将明文的键控散列(例如HMAC)存储在单独的列中。盲索引密钥应该与加密密钥不同并且对数据库服务器是未知的。

据我了解(但我在这里可能是错的)我需要搜索的值是使用每列静态的索引键散列的。在 HMAC 列中搜索结果值。当找到一条记录时,加密的值就会被解密。

他们描述它确实存在重复条目泄漏,这意味着如果获得所有记录,则可以知道哪些记录具有相同的值,但不知道该值是什么。

我理解这些概念,听起来不错,但由于我不是密码专家,我无法真正判断它的安全性。难道不能以某种方式使用这个重复的条目泄漏来进行其他攻击吗?我一直都知道(=在互联网上阅读)加密应该始终包含 IV/Nonce/Salt 以使彩虹表成为不可能。我猜每列使用静态索引键会阻止这些彩虹表。

基本上我觉得我在这里错过了一些东西。为什么重复条目泄漏一下子就不是问题了?还有其他人可以评论这个图书馆/技术吗?

2个回答

重要免责声明:我为我的雇主写了 CipherSweet。除非第三方安全专家另行验证,否则以下所有内容都应持保留态度。即使这个答案得到很多选票,也绝不能被接受。我只是试图回答有关 CipherSweet 设计的一些基本问题,而不是回答它是否安全。而是相信别人。

CipherSweet 的安全模型本质上是一种时间记忆权衡,它引入了比传统密码分析技术更类似于填字游戏的攻击风险(因此,我们将它们简称为“填字游戏攻击”,尽管更多正式术语“部分已知的明文攻击”更有可能在学术文献中找到相关命中)。

在这方面,CipherSweet 的整体设计可以是安全的,但前提是在您的应用程序中设计盲索引时要小心。有几个考虑:

  1. 您将存储每个盲索引的多少位?
    • 更少的位会增加给定 SELECT 查询发生冲突的机会,这意味着在解密后要过滤掉更多的误报。
    • 然而,较少的位也会降低盲索引的有用性。
  2. 您将为给定的加密列创建多少个盲索引?
    • 您创建的索引越多,您泄露给攻击者的元数据就越多。

当然,只有在其他一些假设成立的情况下,这种设计的安全性才值得讨论:

  1. 每个盲索引都有一个不同的键。
  2. 用于将明文转换为盲索引的散列函数(或 KDF)是足够安全的(例如在随机预言模型中)。
  3. 加密本身是安全的(例如,针对所有已知实际攻击的安全级别超过 127 位的 AEAD)。

要了解如何回答这些假设,请阅读CipherSweet 内部文档但简而言之,答案是:

  1. CipherSweet 使用从主密钥派生的不同的每个字段和每个索引键
  2. 截至 2018 年 11 月,HMAC-SHA384 和 BLAKE2b仍未中断。
  3. 截至 2018 年 11 月,AES-CTR + HMAC-SHA2 和 XChaCha20-Poly1305仍未中断。

话虽如此,未回答的问题是:我们如何确定信息泄露的不安全水平?

  • 显然,创建一个不同的盲索引$plaintext[0], $plaintext[1], ... 会从索引中泄漏整个明文。
    • 在这种情况下,您不需要破解加密。只需研究模式并提交虚拟条目并将其视为非常低效的替换密码。
  • 相反,整个明文的单个字面盲索引(截断为 16 位)几乎肯定不会泄露任何对攻击者有用的信息。
    • 给定足够大的数据集,冲突将非常普遍。
    • 当然,这几乎违背了甚至创建盲索引的目的。

此外,Cip​​herSweet 允许您创建复合盲索引例如,您可以一起散列:

  1. 人名的首字母(如适用)
  2. 此人姓氏的首字母(如适用)
  3. 此人的社会安全号码的最后 4 位数字
  4. 一封标识其性别/性别的字母(如果适用)

这极大地增加了给定盲索引的可能明文的键空间,即使每个单独输入的键空间是有限的。这对于使用布尔字段进行加密/搜索特别有用


鉴于以上所有情况,我不知道您是否能够在本网站上获得关于是否信任 CipherSweet 的充分答案。未回答的问题并不完全容易回答,需要深入分析。

话虽如此:以破坏其安全目标的方式滥用CipherSweet肯定是有可能的。这是一个工具。

我相信,除非在协议设计中发现一些深层缺陷,否则应该可以安全地使用 CipherSweet。即使它是安全的,您几乎肯定会希望安全专家仔细检查您如何使用它。

免责声明:虽然我在 ciphersweet 发布时(或至少在我意识到它时)研究了它的设计和实现,但我没有对设计进行全面的审计和安全证明,我也没有不要深入研究 PHP 的实现(很大程度上是因为我没有做太多的 PHP 工作)。不要把它误认为是审计报告(我只在我得到报酬时才做这些:P)

Ciphersweet 使用了一个漂亮而乏味的设计。斯科特在他的回答中解释了这一点,以及 Cyphersweet 的安全声明,所以我不再赘述。IMO Ciphersweet 的主要观点是,它比替代方案更安全、更难搞砸。

您提到的“重复条目泄漏”不适用于完整记录(这些记录使用标准的非确定性加密进行加密),但适用于盲索引:如果您对 HIV 状态进行索引,那么具有数据库读取权限的人可以找出哪些记录具有相同的 HIV 状态,并从那里很可能恢复所有记录的 HIV 状态。

这是盲索引的基础信息泄漏:如果您对SELECT具有给定 HIV 状态(的函数)的所有行有足够的信息,则您有足够的信息来检查任何 2 行是否具有相同的 HIV 状态,因此更高级的密码学在那里无济于事(包括使用确定性加密,顺序保留/显示加密,......)。

好消息是,与其他设计(如显示顺序的加密)不同,键控哈希(在未知密钥下)不会透露比值是否相等更多的信息。

显然,这还不够(如 HIV 状态示例所示),因此您可以使用 3 种主要缓解措施(Ciphersweet 全部支持):

  1. 最明显的是不要在非常敏感的数据上添加盲索引:如果你不想暴露 HIV 状态数据,你为什么要创建一个索引来有效地查询它们?

  2. 使用复合索引:如果您需要索引的数据熵太低而无法安全地放入盲索引(例如 HIV 状态),您可以将其与其他一些数据一起散列(文档提供使用 SSN)例如),并支持SELECT具有给定 HIV 状态给定 SSN 的记录。

    这是 IMO 不太有用的选项,因为您可以直接SELECT通过 SSN(假设您对 SSN 有一个盲索引),然后检查解密记录中的 HIV 状态。将它保留在您无法在其中一个字段上拥有索引的情况下(因为它们都太低熵和/或高灵敏度)。

  3. 截断 HMAC 值,以减少信息泄漏:假设您有患者记录,均具有唯一名称,并支持按其选择 [0]。我可以通过添加具有该名称的记录(通过应用程序)来检查某个患者是否存在,然后检查数据库以查找具有相同名称哈希的第二条记录,即使应用程序本身不会授予我搜索的权限病人的名字。

    使用截断散列,您可以使盲索引中的每次查找(平均)返回少量记录;说,如果你想要平均。每个查询 3 条记录,在 1 000 000 条记录中,您需要一个大小为 log2(10⁶/3) ~ 18 位的散列。这使得我描述的场景变得不可能。

    我不认为 Ciphersweet 为随着数据库大小的增加而发展盲索引的大小提供了特别的支持,尽管它应该是可行的。值得庆幸的是,随着数据库的增长,不调整盲索引大小的唯一问题是轻微的性能开销:如果您的数据库变大 10 倍并且现在包含 10 000 000 条记录,则保持相同的 18 位盲索引会产生 avg。选择了 30 条记录,然后应用程序对其进行解密和过滤;解密 30 条记录以找到您感兴趣的记录应该仍然相当快。

[0] 在实际用例中,您可能会支持通过名称的规范化(小写,去除标点符号)版本进行选择;Ciphersweet 支持功能索引。

TL;DR:Ciphersweet 是安全的,可能比大多数替代方案更安全;您需要注意一些警告,这些警告存在于所有加密数据库中,以及一些操作问题,但它们都非常易于管理。