当前位置: 首页 > 知识库问答 >
问题:

加密数据的全文搜索

芮意
2023-03-14

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

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

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

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

免责声明
我试图构建的是一款消费者级产品,它将处理机密但并非完全机密的数据(在实际实现时需要密码师的帮助;现在我只是想了解这是否可能)
我的目标只是提供足够安全的东西,以便攻击者更容易尝试窃取用户的密码(例如,侵入客户机——最终他们是消费者),而不是花费大量时间和计算能力试图强行创建索引或运行复杂的统计分析。

(可能与回答问题的其他人有关)

>

salt的保护方式与用户的解密密钥(用于解密存储文本的密钥)完全相同。因此,如果有人能够捕捉到盐,他或她很可能也能够捕捉到钥匙,从而产生一个更大的问题
准确地说,密钥和盐将加密存储在服务器上。它们将由客户端使用用户密码在本地解密并保存在内存中;服务器从未看到解密的密钥和salt。用户可以更改密码,他们只需要重新加密密钥和salt,而不是所有存储的文本。据我所知,这是一种相当标准的行业方法。

实际上,数据库的设计如下(仅报告相关条目)。这个设计就像你在评论中提出的那样。它不允许近距离搜索(与我们无关),并降低了频率的准确性。

  • 内容,包含所有加密文本。列是内容。id内容。文本
  • 单词,包含所有哈希的列表。列是单词。id单词。散列
  • match,将文本与散列/单词(以一对多关系)匹配。列是匹配的。内容id匹配。word_id

我们必须实现删除停顿词等功能。当然。这不是一个大问题(当然,将在客户端上完成)。最终,这些列表对国际(即非英语)用户的效用总是有限的。
我们期望查找/插入比率相当高(即许多查找,但很少插入,而且大部分是批量的)。

解密整个哈希数据库当然是可能的,但是需要暴力攻击。
假设盐是安全的(如上面第2点所述)。如果盐足够长(你引用了32位...但是为什么不是320位?-只是一个例子),那将需要很多时间。

总之。。。你证实了我对频率分析可能存在的风险的怀疑。然而,我觉得这种风险并没有那么高。你能证实吗<事实上,首先,每个用户的食盐都是独一无二的。这意味着一次必须攻击一个用户<其次,通过每篇文章只报告一次单词(无论它们出现多少次),频率分析变得不那么可靠<第三。。。例如,对散列词的频率分析听起来不如对凯撒移位的频率分析好。仅英语就有250000个单词(而且,我们的用户也不是都会说英语),即使有些单词比其他单词更常见,我相信无论如何都很难进行这种攻击。

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

共有3个答案

璩华辉
2023-03-14

MSSQL Enterprise TDE在设置整个数据库加密时加密全文索引以及其他索引(自2008年以来)。实际上,它工作得很好,没有巨大的性能损失。不能评论如何,b/c这是一个专有的算法,但这里有文档。

https://docs.microsoft.com/en-us/sql/relational-databases/security/encryption/transparent-data-encryption-tde

除了数据库之外,它不会覆盖任何应用程序堆栈,但FTS索引将像普通索引一样工作,不会像MySQL或PostGres那样以纯文本形式存在。据我记忆所及,MariaDB和Oracle当然也有自己的实现。MySQL和PGSQL则不然。

至于密码,所有实现上的TDE都使用AES密钥,它可以旋转(尽管不总是容易的)——所以密码漏洞落在DBA上。

马哲
2023-03-14

首先,你拥有基于密码的密码学的所有正常漏洞,这些漏洞源于用户挑选可预测的密码。在离线攻击中,用不到两个小时的桌面计算时间破解来自现实世界应用程序的50%以上的密码是很常见的。

我假设全文加密密钥是从密码派生的,或者是由密码派生的密钥加密的。因此,攻击者可以根据所选的散列索引密钥测试猜测,一旦找到密码,就可以解密所有文档。

但是,即使用户选择了一个高熵的密码,对索引的频率分析也有可能揭示大量关于纯文本的信息。尽管索引会丢失词序(如果你不支持邻近搜索),但你实际上是在为每个用户创建一个电子密码本。这个索引很容易受到几个世纪以来发达的密码分析技术的攻击。现代加密协议避免了欧洲央行,并提供了“密文不可区分性”——相同的纯文本每次加密都会产生不同的密文。但这在索引上不起作用。

一种不那么容易受到攻击的方法是在客户端上进行索引和搜索。必要的表将作为一条消息捆绑在一起,并在客户端进行加密,然后传输到服务器进行存储。明显的折衷是每次会话传输该捆绑包的成本。客户端缓存索引片段可以在一定程度上降低这一成本。

最后,只有您可以权衡漏洞的安全成本与客户端索引的性能成本。但通过指数进行的统计分析是一个显著的弱点。

夏骞尧
2023-03-14

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

评论太长了,如果我理解正确的话:

  1. 您已经加密了用户提交的数据(客户端已加密,因此不使用DB来处理)。
  2. 您希望用户能够搜索到这些信息(而您对此一无所知,因此加密的文本块是无用的)。
  3. 您提出的解决方案是存储客户端提交的散列单词列表(或者段落)。

所以数据记录看起来像:

  • 列1:加密数据块
  • 第2列:(空格)从上述加密文本中以散列、有序的单个单词分隔

然后,要搜索,只需对搜索词进行散列,并将散列后的词作为单词来搜索第2列中“文本”的段落。这肯定是有效的-只是考虑搜索无意义的文本与胡说八道搜索条款。你甚至可以用这种方法对术语进行近似排序。

关注:

  1. 与加密文本相比,将单独散列的单词作为文本的列将非常弱。你正在极大地削弱你的解决方案,因为不仅有有限的单词可供使用,生成的文本也会受到词频分析等因素的影响。

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

  1. 在客户端执行搜索(所有数据必须存在于客户端才能搜索)

我理解的论点是,您的方法为用户提供了对其数据的唯一访问权限(即,您无法查看/解密数据)。我认为这种散列方法充分削弱了数据,因此您可以合理地计算出用户数据(也就是说,您已经降低了所需的工作量,以至于您可以在不知道用户密钥/密码的情况下解密用户的信息)。我不会降低门槛来形容这只是混淆,但你应该仔细想想这有多重要。

如果您确信削弱系统来实现这样的搜索是有意义的,而另一种方法是不够的,那么可以帮助您将文本中的单词散列存储为唯一出现的单词列表(即,没有频率或邻近信息可用)。这将稍微减少实现的攻击表面积,但也会失去将该方法描述为FTS所暗示的好处。你可以很快得到这样的结果,因为散列词基本上变成了附加到所有包含它们的记录上的标签。然后,搜索查找可能会变得非常快(以插入为代价)。

*我想明确一点,在我实施之前,我想确定我的业务需求需要这样的东西。。。

编辑:

问题的快速示例——假设我知道你使用的是32位salt,并对“the”等常见单词进行哈希运算。2^32可能的盐分=40亿可能的盐分(也就是说,如果你只需要在最初的攻击中散列几个单词,就不会有那么多)。假设盐被添加或预先添加,这仍然只有80亿个条目需要预先计算。即使是不太常见的词,你也不需要创建太多的列表来确保你会被点击(如果不是这样的话,你的数据就不值得搜索)。

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

我猜,通过访问数据库,你可以在数小时到数天内解密系统中的散列数据。

 类似资料:
  • 我用钠来加密存储在数据库中的个人数据。我可以愉快地加密和解密存储的数据。在数据库中存储时,我正在加密名字和姓氏、电话号码、电子邮件地址等。 然而,我不知道如何搜索加密数据。任何人都能给出加密数据然后搜索数据的指针吗? 例如,我需要按名字、姓氏等进行搜索,但这是加密的。 我用这段代码搜索并认为对名称进行加密是“愚蠢的”,但这当然会对其进行重新加密,然后与实际记录不同。 我甚至不知道该怎么做,到目前为

  • 问题内容: Iam将创建一个包含至少2亿个条目的庞大数据库。该数据库需要使用全文本进行搜索,并且应该是快速的。 我的数据库从许多不同的数据源获取数据,我需要定期导入新数据或更新数据。 将我的所有数据存储在诸如mysql之类的关系数据库中,然后创建一个nosql文档数据库(例如mongodb或elasticsearch)只是出于搜索目的,还是在可靠性和预防方面没有任何好处,这是一个好主意吗?多余的信

  • 我使用的是Micronaut数据版本1.0.2。 给定以下JPA实体类: 我可以使用的以下方法创建全文搜索查询: 但是,我有一个问题,需要为名称属性添加另一个标准。我想要实现的相当于以下SQL: 我测试了以下方式: 知道怎么让它工作吗? 提前感谢。

  • bcrypt 数据加密 文档:https://www.npmjs.com/package/bcryptjs 安装:cnpm i -S bcryptjs [ ] 使用: 封装helper函数 app / extend / helper.js // 引入加密插件 const bcrypt = require('bcryptjs') const jwt = require('jsonwebtoken')

  • EncryptAlgorithm SPI 名称 详细说明 EncryptAlgorithm 数据加密算法 已知实现类 详细说明 MD5EncryptAlgorithm 基于 MD5 的数据加密算法 AESEncryptAlgorithm 基于 AES 的数据加密算法 RC4EncryptAlgorithm 基于 RC4 的数据加密算法 QueryAssistedEncryptAlgorithm S

  • 配置项说明 命名空间:http://shardingsphere.apache.org/schema/shardingsphere/encrypt/encrypt-5.0.0.xsd <encrypt:rule /> 名称 类型 说明 默认值 id 属性 Spring Bean Id queryWithCipherColumn (?) 属性 是否使用加密列进行查询。在有原文列的情况下,可以使用原文