合作机构:阿里云 / 腾讯云 / 亚马逊云 / DreamHost / NameSilo / INWX / GODADDY / 百度统计
前几天,知识星球中有位小伙伴,问了我一个问题:加密的手机号如何模糊查询?
我们都知道,在做系统设计时,考虑到系统的安全性,需要对用户的一些个人隐私信息,比如:登录密码、身份证号、银行卡号、手机号等,做加密处理,防止用户的个人信息被泄露。
很早之前,CSDN遭遇了SQL注入,导致了600多万条明文保存的用户信息被泄。
因此,我们在做系统设计的时候,要考虑要把用户的隐私信息加密保存。
常见的对称加密算法有 AES、SM4、ChaCha20、3DES、DES、Blowfish、IDEA、RC5、RC6、Camellia等。
目前国际主流的对称加密算法是AES,国内主推的则是SM4。
无论是用哪种算法,加密前的字符串,和加密后的字符串,差别还是比较大的。
比如加密前的字符串:苏三说技术,使用密钥:123,生成加密后的字符串为:U2FsdGVkX1+q7g9npbydGL1HXzaZZ6uYYtXyug83jHA=。
如何对加密后的字符串做模糊查询呢?
比如:假设查询苏三关键字,加密后的字符串是:U2FsdGVkX19eCv+xt2WkQb5auYo0ckyw。
上面生成的两个加密字符串差异看起来比较大,根本没办法直接通过SQL语句中的like关键字模糊查询。
那我们该怎么实现加密的手机号的模糊查询功能呢?
实现这个功能,我们第一个想到的办法可能是:把个人隐私数据一次性加载到内存中缓存起来,然后在内存中先解密,然后在代码中实现模糊搜索的功能。
图片
这样做的好处是:实现起来比较简单,成本非常低。
但带来的问题是:如果个人隐私数据非常多的话,应用服务器的内存不一定够用,可能会出现OOM问题。
还有另外一个问题是:数据一致性问题。
如果用户修改了手机号,数据库更新成功了,需要同步更新内存中的缓存,否则用户查询的结果可能会跟实际情况不一致。
比如:数据库更新成功了,内存中的缓存更新失败了。
或者你的应用,部署了多个服务器节点,有一部分内存缓存更新成功了,另外一部分刚好在重启,导致更新失败了。
该方案不仅可能会导致应用服务器出现OOM问题,也可能会导致系统的复杂度提升许多,总体来说,有点得不偿失。
既然数据库中保存的是加密后的字符串,还有一种方案是使用数据库的函数解密。
我们可以使用MySQL的DES_ENCRYPT函数加密,使用DES_DECRYPT函数解密:
SELECT
DES_DECRYPT('U2FsdGVkX1+q7g9npbydGL1HXzaZZ6uYYtXyug83jHA=', '123');
TOP