数据库加密字段进行模糊查询详解
需求
对于一些敏感字段,比如手机号码、身份证、地址、银行卡号等,我们在存放进数据库前,可能需要对其进行加密。
大部分情况下,我们只需要支持等值查询。但是如果需要支持模糊查询,那么整段内容整体加密就不具备这个能力。
下面是几种解决办法,场景是我们需要根据手机号码的前缀进行匹配。
服务器端解密
因为服务器肯定是具备解密密文的能力的,因此最简单的方式就是把整个表的密文字段数据拉下来,在服务器端进行解密,然后再在服务器端进行匹配。
findrecords(prefix) {
records = getallrecords()
finds = []
for (record : records) {
phone = decrypt(record.phone)
if (phone.hasprefix(prefix)) {
finds.push(record)
}
}
return finds
}
如果数据量很小,那么这种做法也许还能够接受。但是只要数据量上去,那么效率就会很低,而且还需要通过网络io把整个表的数据传输到服务器端。
数据库端解密
上面的做法需要把整个表的数据传输到服务器端,那么我们只需要能够在数据库进行匹配,就不需要传输整个表了。因此我们也可以在数据库实现解密算法,在匹配的时候用解密算法解密密文,就能够进行模糊匹配了。
findrecords(prefix) {
return query("select * from table where decrypt(phone) like '?%'", prefix)
}
这个做法也是需要遍历整个数据库,因此只适合数据量比较小的情况下;而且需要把密钥传给数据库,增加了密钥泄露的风险。
字符串分片
上面的做法我们都没有用到数据库的索引能力,正常情况下,前缀匹配我们是可以使用到索引的,比如where phone like 'prefix%'。如果加密后的密文,也能够走索引,那么我们就不需要遍历整个数据表了。
比如我们可以根据4位作为一个检索条件,将手机号码拆分位多个分片:比如手机号012345678901,我们可以拆分并对分片进行加密:
| 分片 | 密文 |
|---|---|
| 0123 | /egpar5g9smquuwwz+3clg |
| 1234 | ehcmzqxnslx/b37koarx/w |
| 2345 | 9w1pv8ik2h41s1korlfpha |
| 3456 | vcfffvi0mwagijdsqjcmsw |
| 4567 | tr/wayfvysymjhcz78rfla |
| 5678 | 2wfec6sgdxx7wmo0ycyy/q |
| 6789 | ffo9qd9xpx/lnjjutftfaa |
| 7890 | wufth7zobley2lmepg5taw |
| 8901 | 1xr5mhrmlqoac5x6cmn3ka |
这些密文拼接起来的串为:
/egpar5g9smquuwwz+3clgehcmzqxnslx/b37koarx/w9w1pv8ik2h41s1korlfphavcfffvi0mwagijdsqjcmswtr/wayfvysymjhcz78rfla2wfec6sgdxx7wmo0ycyy/qffo9qd9xpx/lnjjutftfaawufth7zobley2lmepg5taw1xr5mhrmlqoac5x6cmn3ka
然后就可以支持前缀查询了(最少4位),比如前缀01234,我们可以按照上面的分片方式先分片,再拼接为查询串:
| 分片 | 密文 |
|---|---|
| 0123 | /egpar5g9smquuwwz+3clg |
| 1234 | ehcmzqxnslx/b37koarx/w |
查询串:
/egpar5g9smquuwwz+3clgehcmzqxnslx/b37koarx/w
可以看到查询串为上面的前缀,因此可以进行前缀查询!
代价
这种方式也是会有一定的代价的:
密文长度较长
比如手机号码是明文长度是11,但是按照4位分片的密文长度是198
分片长度不能太短
分片太短有安全问题,因此没办法支持过短的查询。
主要是因为切片过短,会很容易被猜出来每一位对应的密文。比如0-9的密文切片长度1切分:
| 分片 | 密文 |
|---|---|
| 0 | hhjjxa0e+haw/+wz1mfita |
| 1 | y7qhn2nn3ne/6wnriwl/lg |
| 2 | h0dmfko5suolfflp8j2y5a |
| 3 | ma/xrjjpv2mxsxe7y4xs8w |
| 4 | q9v4pxxpjjgdr7uchumy1g |
| 5 | wo57z24uxlobdq7qzxloqa |
| 6 | fc+zrf4ga5tcb5zu36kvrq |
| 7 | z+xqhawmlascnip6nnd3lg |
| 8 | olm8cpymlhced1jegauiww |
| 9 | hjs77tlmd2ol5su4dibbpw |
只有10种分片类型,如果对应的是手机号码字段,很容易根据统计每个数字的概率分布猜出每个数字对应的密文。
可能有多余结果
可能有两个不同分片对应相同密文,这时候就需要在服务器再过滤一遍。
参考
密文字段检索方案
实现
golang实现基于aes+cbc+pkcs5padding的可模糊查询加密
以上就是数据库加密字段进行模糊查询详解的详细内容,更多关于数据库加密字段模糊查询的资料请关注萬仟网其它相关文章!
看完文章,还可以扫描下面的二维码下载快手极速版领4元红包
除了扫码领红包之外,大家还可以在快手极速版做签到,看视频,做任务,参与抽奖,邀请好友赚钱)。
邀请两个好友奖最高196元,如下图所示:







