全文搜索加密数据

 岩律_619 发布于 2023-01-19 10:11

假设我有一个存储加密文本的服务器(端到端:服务器永远不会看到纯文本).

我希望能够对该文本进行全文搜索.
我知道这很棘手,但我的想法是使用传统的全文设计("列表"和"匹配"表,其中单词存储并与内容表中的ID匹配).当用户提交加密文本时,他们还会发送单词和相应匹配的盐渍MD5.使用的盐对每个用户都是唯一的,并从密码中恢复.
(简而言之:唯一的区别是"list"表将包含散列词)

现在,这个系统有多脆弱
请注意,我说"多么脆弱"而不是"多么安全",因为我承认它不是完全安全的.
我理解功能(全文搜索)和安全性(从单词索引中披露一些信息)之间的权衡.例如,据我所知,能够获取列表和匹配表的攻击者可以获得有关原始加密文本的信息,并且可能能够通过统计分析来解读某些单词(但是,对于每个用户来说,这是唯一的盐,这将需要为每个用户重复).

这种威胁有多严重?还会有其他严重的威胁吗?

免责声明
我正在努力建立(并在密码学家的帮助下进行实际实施;现在我只是想了解这是否可行)是一种消费级产品,它将处理机密而不是完全保密数据.
我的目标只是提供足够安全的东西,以便攻击者更容易尝试窃取用户的密码(例如,破坏客户端 - 他们最终是消费者),而不是花费大量时间和计算能力尝试蛮力指数或运行复杂的统计分析.

回应@Matthew的评论

(可能与其他人回答相关)

    如您所述,其他解决方案并不可行.将所有数据存储在客户端内意味着用户无法从其他客户端访问其数据.服务器端加密可以工作,但是我们将无法为用户提供额外的客户端加密安全性.
    唯一的"真正替代方案"就是不实现搜索:虽然这不是必需的功能,但对我/我们来说非常重要.

    盐将以与用户的解密密钥(用于解密存储的文本的密钥)完全相同的方式受到保护.因此,如果有人能够捕获盐,他或她可能也能够捕获关键,从而产生更大的问题.
    确切地说,密钥和盐将以加密方式存储在服务器上.它们将由客户端使用用户的密码在本地解密并保存在内存中; 服务器永远不会看到解密的密钥和盐.用户可以更改密码,然后他们只需要重新加密密钥和盐,而不是所有存储的文本.据我所知,这是业界非常标准的方法.

    实际上,数据库的设计如下(仅报告相关条目).这个设计就像你在评论中提出的那样.它不允许接近搜索(与我们不太相关)并且使频率不准确.

    content,包含所有加密文本.列是content.idcontent.text.

    words,包含所有哈希的列表.列是words.idwords.hash.

    match,匹配带有哈希/单词的文本(以一对多的关系).列是match.content_idmatch.word_id.

    我们必须实现删除停用词等功能.当然.这不是一个大问题(当然,将在客户端完成).最终,这些列表对于国际(即非英语用户)用户来说一直有限.
    我们希望查找/插入比率非常高(即很多查找,但很少有插入,主要是批量).

    解密整个哈希数据库肯定是可能的,但需要强力攻击.
    假设盐是安全的(按照上面的第2点).如果盐足够长(你引用32位......但为什么不是320? - 只是一个例子)需要花费很多时间.

总结......你证实了我对频率分析可能存在风险的疑虑.但是,我觉得这种风险并不是那么高.你能证实吗?
实际上,首先,每个用户的盐都是唯一的.这意味着一个用户必须及时受到攻击.
其次,通过每个文本仅报告一次单词(无论它们出现多少次),频率分析变得不太可靠.
第三......例如,散列词的频率分析听起来不像凯撒移位的频率分析那么好.仅英语就有250,000个单词(并且,并非所有用户都会说英语),即使某些单词比其他单词更常见,我相信无论如何都很难做到这种攻击.

PS:我们要存储的数据是消息,如即时消息.这些都很简短,包含很多缩写,俚语等.每个人在撰写文本时都有不同的风格,进一步降低了频率攻击的风险(在我看来).

1 个回答
  • TL; DR:如果这需要足够安全,需要每个用户端到端加密:不要这样做.

    评论太长了,所以这里 - 如果我理解正确的话:

      您有用户提交的加密数据(客户端加密,因此不使用DB来处理).

      您希望这可以被用户搜索(在您不知道任何相关信息的情况下 - 因此加密的文本块是无用的).

      您提出的解决方案是同时存储从客户端提交的散列单词列表(或可能是段落).

    所以数据记录看起来像:

    第1列:加密数据块

    第2列:(空格)从上面的加密文本中分隔出散列的,有序的单个单词

    然后搜索你只是哈希搜索术语并将散列术语视为单词来搜索第2列中"文本"的段落.这肯定有效 - 只考虑用无意义的搜索术语搜索无意义的文本.您甚至可以使用此方法对术语进行一些接近排名.

    关注:

      与加密文本相比,具有单独散列的单词作为文本的列将非常弱.您正在大大削弱您的解决方案,因为不仅可以使用有限的单词,生成的文本将容易受到词频分析等的影响.

      如果您这样做:单独存储与密码无关的salt.如果你的盐被捕获,那么很容易创建一个彩虹表(仅限字典单词)将它存储在某处加密.

      您将失去FTS的许多好处,例如忽略像'the'这样的词 - 如果您需要,您将需要自己重新实现此功能(即在提交数据/搜索术语之前在客户端删除这些术语).

    您暗示的其他方法是不可接受/可行的:

      实现搜索客户端(所有数据必须存在于客户端上才能搜索)

      集中加密利用内置功能的数据库

    我理解的观点是,您的方法为用户提供了对其数据的唯一访问权限(即您无法查看/解密它).我认为这种散列方法会充分削弱数据,以便您可以合理地计算出用户数据(也就是说,您已经降低了所需的工作量,以至于您可以在不知道其密钥的情况下解密用户的信息这一点非常合理/盐).我不会低估将其描述为混淆,但你应该仔细考虑这是多么重要.

    如果你确定弱化你的系统以实现这样的搜索是有道理的,而另一种方法是不够的,那么可以帮助的一件事就是将文本中的单词的哈希值存储为唯一存在的单词列表(即不频率或接近度信息可用).这会稍微减少实现的攻击面积,但是通过将方法描述为FTS也会失去您所暗示的所需的好处.你可以获得非常快速的结果,尽管散列的单词基本上成为附加到包含它们的所有记录的标签.然后搜索查找可能变得非常快(以插入为代价).

    *只是要明确一点 - 在我实施之前,我真的希望确保我的业务需求需要这样的东西......

    编辑:

    问题的快速示例 - 比如我知道你使用的是32位盐,并且正在使用像"the"这样的常用词.2 ^ 32种可能的盐= 40亿种可能的盐(也就是说,如果你只需要为初始攻击散列一些单词,那就不是很多了).假设盐被附加或预先附加,这仍然只有80亿条预先计算.即使它不常见,你也不需要创建太多的列表来确保你会得到命中(如果不是这种情况,你的数据就不值得搜索).

    然后在我们的每个预先计算的盐表中查找给定文本块的最高频率盐,并使用匹配来查看它是否正确解密文本中的其他单词.一旦你有一个合理的候选人为该盐生成250,000字英语彩虹表并解密文本.

    我猜你可以在几小时到几天内解密系统中的散列数据并访问数据库.

    2023-01-19 10:14 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有