对加密数据进行全文搜索
假设我有一台存储加密文本的服务器(端到端:服务器从不看纯文本)。
我希望能够对该文本进行全文搜索。
我知道这很棘手,但我的想法是使用传统的全文设计(“列表”和“匹配”表,其中单词被存储并与来自内容表的ID匹配)。 当用户提交加密的文本时,他们还会发送一个盐和MD5的单词和各自的匹配。 所使用的盐对每个用户都是唯一的,并且从密码中恢复。
(简而言之:唯一的区别是“列表”表将包含散列字)
现在,这个系统有多脆弱?
请注意,我说“多么脆弱”而不是“多么安全”,因为我承认它不是完全安全的。
我理解功能(全文搜索)和安全性之间的权衡(公开一些来自单词索引的信息)。 例如,我知道能够获取列表和匹配表的攻击者可以获取有关原始加密文本的信息,并可能通过统计分析来破译某些单词(但是,对于每个用户而言,盐是唯一的,这需要为每个用户重复)。
这种威胁会有多严重? 还会有其他严重的威胁吗?
免责声明
我正在试图建立的(并在密码学家的帮助下进行实际实施;现在我只是想了解这将是可能的)是一种消费级产品,它将处理机密但不是完全秘密的数据。
我的目标是提供足够安全的东西,以便攻击者可以更轻松地窃取用户的密码(例如,最终侵入客户端 - 最终是消费者),而不是花费大量时间和计算能力尝试蛮横指数或运行复杂的统计分析。
回应@Matthew的评论
(可能与其他人的回答有关)
正如你所指出的,其他解决方案是不可行的。 将所有数据存储在客户端中意味着用户无法从其他客户端访问其数据。 服务器端加密可以起作用,但我们无法为用户提供增强的客户端加密安全性。
唯一的“真正的选择”就是不执行搜索:虽然这不是必需的功能,但对我/我们来说非常重要。
盐的保护方式与用户的解密密钥(用于解密存储的文本的密钥)完全相同。 因此,如果有人能够捕获盐,他或她可能也能够捕获关键,创造一个更大的问题。
确切地说,密钥和盐将在服务器上被加密存储。 它们将由客户在本地用用户密码解密并保存在内存中; 服务器从不会看到解密的密钥和盐。 用户可以更改密码,然后他们只需要重新加密密钥和盐,而不是所有存储的文本。 据我所知,这是业界非常标准的方法。
实际上,数据库的设计如下(仅报告相关条目)。 这种设计就像您在评论中提出的一样。 它不允许邻近搜索(与我们不太相关)并且使频率不准确。
content
,包含所有加密文本。 列是content.id
和content.text
。 words
,包含所有哈希列表。 列是words.id
和words.hash
。 match
,它将文本与哈希/单词相匹配(以一对多的关系)。 列是match.content_id
和match.word_id
。 我们将不得不实施删除停用词等功能。当然。 这不是一个大问题(当然,会在客户端完成)。 最终,这些列表对于国际(即非英语)用户而言一直具有有限的效用。
我们预计查找/插入比率相当高(即许多查找,但很少见插入,大部分是批量查找)。
解密整个散列数据库当然是可能的,但需要暴力攻击。
假设盐保持安全(按照上述第2点)。 如果盐足够长(你引用32位......但为什么不是320? - 只是一个例子),这将需要很多时间。
总结...您证实了我对频率分析的可能风险的怀疑。 但是,我觉得这个风险不是很高。 你能证实吗?
事实上,首先盐每个用户都是独一无二的。 这意味着一个用户必须在一段时间内受到攻击。
其次,通过每个文本仅报告一次词语(无论出现多少次),频率分析变得不太可靠。
第三...例如,散列词的频率分析听起来不像频率分析那样好。 单单英文就有25万个单词(并且,并非所有的用户都会讲英语),即使有些单词比其他单词更普遍,但我认为无论如何也很难做到这一点。
PS:我们要存储的数据是消息,比如即时消息。 这些都很简短,包含很多缩写,俚语等。每个人在写作文本时都有不同的风格,这进一步降低了频率攻击的风险(在我看来)。
TL; DR:如果这需要足够安全以至于需要按用户端到端加密:不要这样做。
太长的评论,所以在这里 - 如果我理解正确:
所以数据记录如下所示:
然后搜索你只需要散列搜索词并将散列词作为单词来搜索第2列中“文本”的段落。这肯定会起作用 - 只要考虑用无意义的搜索词搜索无意义的文本即可。 你甚至可以用这种方法对术语进行近似排序。
关注:
你暗示的其他方法是不可接受/可行的:
我理解这样的观点,即你的方法为用户提供了对他们数据的唯一访问(即你无法看到/解密它)。 我认为这种散列方法会充分削弱数据,从而可以合理地计算出用户数据(也就是说,您已经降低了所需的工作量,以至于您可以在不知道密钥的情况下解密用户的信息/盐)。 我并不想把这个形容为混淆,而是应该真正考虑这个问题的重要性。
如果你确定弱化你的系统来实现这样的搜索是有道理的,而另一种方法是不够的,那么可以帮助的一件事就是将文本中的单词哈希存储为仅有唯一出现的单词列表(即,否频率或邻近信息将可用)。 这会稍微减少实施的攻击面积,但也会通过将该方法描述为FTS而丧失您想要的好处。 你可以得到像这样非常快的结果,不过由于散列字实际上成为附加到包含它们的所有记录的标签。 搜索查找然后可能变得非常快(以您的插入为代价)。
* 要明确 - 我希望在实施之前真正确定我的业务需求是这样的。
编辑:
问题的简单例子 - 说我知道你正在使用32位盐,并散列常见单词如“the”。 2 ^ 32种可能的盐类= 40亿种可能的盐类(也就是说,如果您只需要为最初的攻击散列少数几个词,那么就不会那么多)。 假设盐被附加或预先计算,这仍然只有80亿条预先计算。 即使不那么常见,你也不需要创建太多列表来确保你会得到命中(如果情况并非如此,那么你的数据就不值得搜索)。
然后在我们的每个预先计算的盐表中查找给定文本块的最高频率盐,并使用匹配查看它是否正确解密了文本中的其他词。 一旦你有一个合理的候选人为该盐生成250,000字英语彩虹表并解密文本。
我想你可以在几小时到几天内访问数据库来解密系统中的散列数据。
首先,您拥有基于密码的密码学的所有常见漏洞,这些漏洞源自用户选择可预测的密码。 在离线攻击中,通过破解真实世界应用程序中超过50%的密码,桌面计算时间少于两小时。
我假定全文加密密钥是从密码派生的,或者是通过密码派生密钥加密的。 因此,攻击者可以对选定的散列索引键进行猜测,一旦找到密码,就会解密所有文档。
但是,即使用户选择了高熵密码,对索引进行频率分析也可能会揭示很多关于纯文本的信息。 虽然索引中的字词顺序丢失(如果您不支持邻近搜索),但您基本上是为每个用户创建一个电子代码簿。 这个指数很容易受到几个世纪发达的密码分析技术的影响。 现代加密协议避免了ECB,并提供了“密文不可区分性” - 每次加密时相同的明文产生不同的密文。 但是这对索引不起作用。
不太容易受到攻击的方法是在客户端进行索引和搜索。 必要的表格将被捆绑成一条消息并在客户端加密,然后传输到服务器进行存储。 明显的折衷是在每个会话中传输该捆绑包的成本。 索引片段的客户端缓存可以在一定程度上降低这种成本。
最后,只有您可以权衡违反安全成本与客户端索引的性能成本。 但是由索引启用的统计分析是一个重大漏洞。
MSSQL Enterprise TDE在设置整个数据库加密(自2008年起)时加密全文索引以及其他索引。 在实践中,它工作得很好,没有巨大的性能损失。 不能评论如何,它是一个专有的算法,但是它的文档。
https://docs.microsoft.com/en-us/sql/relational-databases/security/encryption/transparent-data-encryption-tde
它不包括除db之外的任何应用程序堆栈,但是您的FTS索引将像正常一样工作,并且不会像MySQL或PostGres中那样以纯文本形式存在。 从我记忆中,MariaDB和Oracle当然也有自己的实现。 MySQL和PGSQL不。
至于密码,所有实现中的TDE都使用AES密钥,这些密钥可以旋转(尽管并非易事),所以密码漏洞落在DBA的漏洞之中。
问题是你需要支付MSSQL TDE的完整企业许可证(即在“标准”或“基本”云和内部版本中不具备的功能),并且你也可能在Oracle中使用TDE。 但是,如果你需要的是一个快速解决方案并且拥有获得企业许可的现金(可能比开发自己的实现便宜),那么实现就在那里。
链接地址: http://www.djcxy.com/p/78037.html上一篇: Full text search on encrypted data
下一篇: word args to array