前言
对加密后的数据进行模糊查询是一项挑战,因为加密过程通常会导致数据失去其原始的可读性和结构,这使得直接在加密数据上进行传统的模糊匹配变得不可行。以下是一些可能的解决方案:
- 索引和映射:在数据库中实现一个额外的索引或映射,这个索引包含了加密数据的某种形式的分词组合。在查询时,可以先对查询条件进行分词,然后将这些分词加密并与索引进行匹配。这种方法需要在加密数据时就考虑如何创建有效的索引。
- 同态加密:使用同态加密技术,这种技术允许在加密数据上直接进行计算,而无需解密。这样,您可以在不暴露原始数据的情况下执行模糊查询。但是,同态加密通常计算成本较高,可能不适合大规模数据处理。
- 代理重加密:代理重加密允许将数据从一个密钥转换为另一个密钥,而无需解密和重新加密。这种方法可以在服务器端实现解密算法,然后对数据进行模糊查询,而不需要将整个表的数据传到客户端。
- 安全多方计算:通过安全多方计算协议,多个参与方可以共同计算一个函数,而不需要任何一方泄露其输入。这种方法可以用于在不暴露原始数据的情况下进行模糊查询。
- 局部解密:在某些情况下,如果查询模式是已知的,可以选择性地解密数据的一部分以进行匹配。这要求查询模式与加密算法兼容,并且能够保证安全性。
- 全文搜索引擎:使用支持加密搜索的全文搜索引擎,如Elasticsearch的某些插件,可以在不暴露原始数据的情况下进行模糊查询。
- 定制加密方案:设计一个定制的加密方案,允许在保持数据安全性的同时进行一定程度的模糊匹配。这可能需要在加密算法和数据结构上进行创新。
- 数据脱敏:在不影响模糊查询结果的前提下,对数据进行脱敏处理,使得数据在保持一定可用性的同时,保护了敏感信息。
- 近似匹配算法:研究和应用近似字符串匹配算法,这些算法可以在不完全匹配的情况下找到相似的字符串,但需要根据加密数据的特点进行调整。
- 专业服务:考虑使用第三方提供的加密数据搜索服务,这些服务可能提供了成熟的解决方案来处理这类问题。
总的来说,您可以通过上述方法来实现对加密后的数据进行模糊查询。请注意,每种方法都有其优势和局限性,选择哪种方法取决于具体的应用场景、性能要求、安全性需求以及可用资源。在实施任何解决方案之前,建议进行彻底的安全评估和性能测试。
沙雕做法
-
将所有数据加载到内存中进行解密,解密后通过程序算法来模糊匹配
-
将密文数据映射一份明文映射表,俗称tag表,然后模糊查询tag来关联密文数据
沙雕一
我们先来看看第一个做法,将所有数据加载到内存中进行解密,这个如果数据量小的话可以使用这个方式来做,这样做既简单又实惠,如果数据量大的话那就是灾难,我们来大致算一下。
一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间,用DES来举例,13800138000
加密后的串HE9T75xNx6c5yLmS5l4r6Q==
占24个字节。
条数 | Bytes | MB |
---|---|---|
100w | 2400万 | 22.89 |
1000w | 2.4亿 | 228.89 |
1亿 | 24亿 | 2288.89 |
轻则上百兆,重则上千兆,这样分分钟给应用程序整成Out of memory,这样做如果数据少只有几百、几千、几万条时是完全可以这样做的,但是数据量大就强烈不建议了。
沙雕二
我们再来看第二个做法,将密文数据映射一份明文映射表,然后模糊查询映射表来关联密文数据,what???!!!那我们为什么要对数据加密呢,直接不加密不是更好么!
我们既然对数据加密肯定是有安全诉求才会这样做,增加一个明文的映射表就违背了安全诉求,这样做既不安全也不方便完全是脱裤子放x,多此一举,强且不推荐。
常规做法
我们接下来看看常规的做法,也是最广泛使用的方法,此类方法及满足的数据安全性,又对查询友好。
-
在数据库实现加密算法函数,在模糊查询的时候使用
decode(key) like '%partial%
-
对密文数据进行分词组合,将分词组合的结果集分别进行加密,然后存储到扩展列,查询时通过
key like '%partial%'
常规一
在数据库中实现与程序一致的加解密算法,修改模糊查询条件,使用数据库加解密函数先解密再模糊查找,这样做的优点是实现成本低,开发使用成本低,只需要将以往的模糊查找稍微修改一下就可以实现,但是缺点也很明显,这样做无法利用数据库的索引来优化查询,甚至有一些数据库可能无法保证与程序实现一致的加解密算法,但是对于常规的加解密算法都可以保证与应用程序一致。
如果对查询性能要求不是特别高、对数据安全性要求一般,可以使用常见的加解密算法比如说AES、DES之类的也是一个不错的选择。
如果公司有自己的算法实现,并且没有提供多端的算法实现,要么找个算法好的人去研究吃透补全多端实现,要么放弃使用这个办法。
常规二
对密文数据进行分词组合,将分词组合的结果集分别进行加密,然后存储到扩展列,查询时通过key like '%partial%',这是一个比较划算的实现方法,我们先来分析一下它的实现思路。
先对字符进行固定长度的分组,将一个字段拆分为多个,比如说根据4位英文字符(半角),2个中文字符(全角)为一个检索条件,举个例子:
ningyu1
使用4个字符为一组的加密方式,第一组ning ,第二组ingy ,第三组ngyu ,第四组gyu1 … 依次类推。
如果需要检索所有包含检索条件4个字符的数据比如:ingy ,加密字符后通过 key like “%partial%”
查库。
我们都知道加密后长度会增长,增长的这部分长度存储就是我们要花费的额外成本,典型的使用成本来换取速度,密文增长的幅度随着算法不同而不同以DES举例,13800138000
加密前占11个字节,加密后的串HE9T75xNx6c5yLmS5l4r6Q==
占24个字节,增长是2.18倍,所以一个优秀的算法是多么的重要,能为公司节省不少成本,但是话又说回来算法工程师的工资也不低,所以我也不知道是节省成本还是增加成本,哈哈哈…你们自己算吧。
回到主题,这个方法虽然可以实现加密数据的模糊查询,但是对模糊查询的字符长度是有要求的,以我上面举的例子模糊查询字符原文长度必须大于等于4个英文/数字,或者2个汉字,再短的长度不建议支持,因为分词组合会增多从而导致存储的成本增加,反而安全性降低。
大家是否都对接过 淘宝、拼多多、JD他们的api,他们对平台订单数据中的用户敏感数据就是加密的同时支持模糊查询,使用就是这个方法,下面我整理了几家电商平台的密文字段检索方案的说明,感兴趣的可以查看下面链接。
-
淘宝密文字段检索方案:https://open.taobao.com/docV3.htm?docId=106213&docType=1
-
阿里巴巴文字段检索方案:https://jaq-doc.alibaba.com/docs/doc.htm?treeId=1&articleId=106213&docType=1
-
拼多多密文字段检索方案:https://open.pinduoduo.com/application/document/browse?idStr=3407B605226E77F2
-
京东密文字段检索方案:https://jos.jd.com/commondoc?listId=345
ps. 基本上都是一样的,果然都是互相抄袭,连加密后的数据格式都一致。
这个方法优点就是实现起来不算复杂,使用起来也较为简单,算是一个折中的做法,因为会有扩展字段存储成本会有升高,但是可利用数据库索引优化查询速度,推荐使用这个方法。
超神做法
我们接下来看看优秀的做法,此类做法难度较高,都是从算法层面来考虑,有些甚至会设计一个新算法,虽然已有一些现成的算法参考,但是大多都是半成品无法拿来直接使用,所以还是要有人去深入研究和整合到自己的应用中去。
从算法层面思考,甚至会设计一个新算法来支持模糊查找
这个层面大多是专业算法工程师的研究领域,想要设计一个有序的、非不可逆的、密文长度不能增长过快的算法不是一件简单的事情,大致的思路是这样的,使用译码的方式进行加解密,保留密文和原文一样的顺序,从而支持密文模糊匹配,说的比较笼统因为我也不是这方面的专家没有更深一步的研究过,所以我从网上找了一些资料可以参考一下。
-
数据库中字符数据的模糊匹配加密方法:https://www.jiamisoft.com/blog/6542-zifushujumohupipeijiamifangfa.html
这里提到的Hill密码处理和模糊匹配加密方法FMES可以重点看看.
-
一种基于BloomFilter的改进型加密文本模糊搜索机制研究:http://kzyjc.cnjournals.com/html/2019/1/20190112.htm
-
支持快速查询的数据库如何加密:https://www.jiamisoft.com/blog/5961-kuaisuchaxunshujukujiami.html
-
基于Lucene的云端搜索与密文基础上的模糊查询:https://www.cnblogs.com/arthurqin/p/6307153.html
基于Lucene的思路就跟我们上面介绍的常规做法二类似,对字符进行等长度分词,将分词后的结果集加密后存储,只不过存储的db不一样,一个是关系型数据库,一个是es搜索引擎。
-
云存储中一种支持可验证的模糊查询加密方案:http://jeit.ie.ac.cn/fileDZYXXXB/journal/article/dzyxxxb/2017/7/PDF/160971.pdf