【MySQL】敏感数据加密后如何模糊查询?
往期文章:
【MySQL】索引
【MySQL】索引底层的数据结构 B+Tree
【MySQL】SQL语句执行流程
【MySQL】order by 的排序策略
【MySQL】explain 执行计划各字段解析
一、前言
在日常开发中,我们通常需要对敏感数据进行加密存储,如:手机号、身份证号码、银行卡号等。
但是此时就会出现一个问题,这些信息对加解密的要求也不一样,比如说密码,一般使用的都是不可逆的慢 hash 算法,慢 hash 算法可以避免暴力破解(典型的用时间换安全性)。
在检索时我们既不需要解密也不需要模糊查找,直接使用密文完全匹配,但是手机号就不能这样做,因为手机号我们要查看原信息,并且对手机号还需要支持模糊查找。
关于这个问题,有多种解决方案,这些方案也是各有优劣,下面就一起来看看都有哪些方案。
二、先解密,再匹配
具体的做法就是将所有数据加载到内存中进行解密,解密后通过程序算法来模糊匹配。
一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间。
就用 DES 加密算法来举例,hello world 加密后的密文是 def3f8ea781a12413b35b1c41f13ab32 占32个字节
条数 | Bytes | MB |
100w | 3200万 | 30.52 |
1000w | 3.2亿 | 305.18 |
1亿 | 32亿 | 3051.76 |
可以看出,这种做法实现很简单,但是也存在一个很明显的问题,数据量小时完全没问题,一旦数据量增大,很容易就会导致 OOM,简直就是灾难!
所以不建议采用!!!
二、映射表
将密文数据映射一份明文映射表,然后模糊查询映射表来关联密文数据。
那为什么还要对数据加密呢,直接不加密不是更好么!
我们既然对数据加密肯定是有安全诉求才会这样做,增加一个明文的映射表就违背了安全诉求,这样做既不安全也不方便完全是画蛇添足,多此一举。
所以不建议采用!!!
三、数据库层面加密
在数据库中实现与程序一致的加解密算法,修改模糊查询条件,使用数据库加解密函数先解密再模糊查找,这样做的优点是实现成本低,开发使用成本低,只需要将以往的模糊查找稍微修改一下就可以实现。
但是缺点也很明显,这样做无法利用数据库的索引来优化查询,甚至有一些数据库可能无法保证与程序实现一致的加解密算法,但是对于常规的加解密算法都可以保证与应用程序一致。
如果对查询性能要求不是特别高、对数据安全性要求一般,可以使用常见的加解密算法比如说AES、DES之类的也是一个不错的选择。
如果公司有自己的算法实现,并且没有提供多端的算法实现,要么找个算法好的人去研究吃透补全多端实现,要么放弃使用这个办法。
四、分词
普通的加密模式下,整段内容会被整体加密,密文就不再具备被模糊查询的功能。
考虑到某些字段存在模糊查询的求,可以使用一种高级的加密模式,加密后的密文仍然可以支持模糊查询功能。
在普通加密方式下,我们在数据库检索该加密数据的时候必须用全文匹配。如姓名:“张大铁”,用普通方式加密后成为 “DQ21aTz/oe9qT2Xje1tTcddQ”,在数据库查询时,如果希望获取关于 ”张大铁” 的记录,则对应筛选条件就是筛选出加密姓名为 “DQ21aTz/oe9qT2Xje1tTcddQ” 的记录。
然而,如果是想检索姓名中含有 “大铁” 的人的记录,原本可以用数据库模糊查询(如 SQL 的 like 语句)方式获取,现在加密后就无法满足这样的要求了。
此时便可以采用对密文数据进行分词组合,将分词组合的结果集分别进行加密,然后存储到扩展列的方式,查询时通过 key like '%partial%',这是一个比较划算的实现方法。
具体做法:根据4位英文字符(半角),2个中文字符(全角)为一个检索条件。将一个字段拆分为多个。
比如:qiuxuan,使用4个字符为一组的加密方式。
第一组 qiux ,第二组 iuxu ,第三组 uxua ,第四组 xuan … 依次类推
如果需要检索所有包含检索条件 4 个字符的数据 比如:uxua,加密字符后通过 key like “%partial%” 查库。
但是使用这种方式也有一定代价:
• 支持模糊查询加密方式,产出的密文比较长;
• 支持的模糊查询子句长度必须大于等于4个英文/数字,或者2个汉字。不支持过短的查询(出于安全考虑);
• 返回的结果列表中有可能有多余的结果,需要增加筛选的逻辑:对记录先解密,再筛选;
对每一个字段都需要独立设置这个字段的加密模式,而且加密后密文长度会膨胀几倍以上,这是需要考虑的点,使用前需根据应用场景确认每个字段的加密方案,一旦加密开始之后,再更改成本就较高了。
这个方法优点就是实现起来不算复杂,使用起来也较为简单,算是一个折中的做法,因为会有扩展字段存储成本会有升高,但是可利用数据库索引优化查询速度,所以还是比较推荐使用这个方法。
参考文章:
被问懵了,加密后的数据如何进行模糊查询?https://cloud.tencent.com/developer/article/2085806
一 叶 知 秋,奥 妙 玄 心