首页 > 其他分享 >加密的手机号如何做模糊查询

加密的手机号如何做模糊查询

时间:2024-02-21 16:44:43浏览次数:15  
标签:encrypt 手机号 模糊 查询 字符串 加密

我们都知道在做系统设置的时候要考虑系统的安全性,需要对一些用户的个人隐私信息,比如:登录密码,身份证号,银行卡号,手机号等进行加密处理,防止用户的个人隐私被泄露。

常见的加密算法有AES、SM4、ChaCha20、3DES、DES、Blowfish、IDEA、RC5、RC6、Camellia等

目前国际主流的对称加密算法是AES,国内主推的则是SM4

无论是用哪种算法,加密前的字符串和加密后的字符串,差别还是比较大的

比如加密前的字符串:123456
使用密钥:WPUOa5zl8Niyl89RcF6qbg==
生成加密后的字符串为:xlK5on8X4FVBCXhrW1LGRw==

如何对加密后的字符串做模糊查询呢

比如查询123关键字
生成加密后的字符串为:NFyMmH+NFmjQwe7W8i8iyQ==
上面生成的两个字符串差异看起来比较大,根本没办法直接通过SQL语句中的like关键字模糊查询
那我们该怎么实现加密的手机号的模糊查询呢?

1.一次加载到内存
实现这个功能,我们第一个想到的办法可能是把个人隐私数据一次性加载到内存中缓存起来,然后在内存中先解密然后在代码中实现模糊搜索的功能

图片这样做的好处是:实现起来比较简单,成本非常低

但带来的问题是:如果个人隐私数据非常多的话,应用服务器的内存不一定够用,可能会出现OOM问题

还有另外一个问题是:数据一致性问题
如果用户修改了手机号,数据库更新成功了,需要同步更新内存中的缓存,否则用户查询的结果可能会跟实际情况不一致
比如:数据库更新成功了,内存中的缓存更新失败了,或者你的应用部署了多个服务器节点,有一部分内存缓存更新成功了,另一部分刚好在重启,导致更新失败了
该方案不仅可能会导致应用服务器出现OOM问题,也可能会导致系统的复杂度提升许多
总体来说有点得不偿失

2.使用数据库函数
既然数据库中保存的是加密后的字符串,还有一种方案是使用数据库的函数解密
我们可以使用MySQL的DES_ENCRYPT函数加密,使用DES_DECRYPT函数解密

如图所示:应用系统中所有的用户隐私信息的加解密都在MySQL层实现,不存在加解密不一致的情况
该方案中保存数据时只对单个用户的数据进行操作,数据量比较小,性能还好,但模糊查询数据时,每一次都需要通过DES_DECRYPT函数把数据库用用户某个隐私信息字段的所有数据解密了,然后再通过解密后的数据做模糊查询,如果该字段的数据量非常大,这样每次查询的性能会非常差

3.分段保存
我们可以将一个完整的字符串拆分成多个小的字符串,以手机号为例16602740823按每3位为一组进行拆分,0-3之后1-4
拆分后的字符串为:166660602027274740408082823,这九组数据
然后建一张表:这张表有三个字段
id:系统编号
ref_id:主业务表的系统编号,比如用户表的系统编号
encrypt_value:拆分后的加密字符串

用户在写入手机号的时候
同步把拆分之后的手机号分组数据也一起写入,可以保证在同一个事务当中,保证数据的一致性
如果要模糊查询手机号,可以直接通过encrypt_value_mapping的encrypt_value模糊查询出用户表的ref_id再通过ref_id查询用户信息

具体的sql如下:

SELECT
	s2.id,
	s2.username,
	s2.phone 
FROM
	encrypt_value_mapping s1
	INNER JOIN `user` s2 ON s1.ref_id = s2.id 
WHERE
	s1.encrypt_value = 'dR4ZDy1dygKQ5eppuprE/g=='

这样就能通过模糊查询搜索出我们想要的手机号了,这里的encrypt_value用的是=,由于是等值查询,效率比较高
注意:这里通过sql语句查询出来的手机号是加密的,在接口返回给前端之前需要在代码中统一做解密处理,为了安全性,还可以将解密后的明文用*增加一些干扰项,防止手机号被泄露,最后展示给用户的内容可以是166*****823

其他的模糊查询,如果除了用户手机号还有其他的用户隐私字段需要模糊查询的场景,我们可以将encrypt_value_mapping表扩展一下,增加一个type字段,该字段表示数据的类型
比如:1.手机号、2.身份证、3.银行卡号等
这样如果有身份证和银行卡号模块查询的业务场景,我们可以通过type字段做区分,也可以使用这套方案,将数据写入到encrypt_value_mapping表,最后根据不同的type查询出不同的分组数据
如果业务表中的数据量少,这套方案是可以满足需求的,但如果业务表中的数据量很大,一个手机号就需要保存9条数据,一个身份证或者银行卡号也需要保存很多条数据,这样会导致encrypt_value_mapping表的数据急剧增加,可能会导致这张表非常大,最后的后果是非常影响查询性能,那么这种情况该怎么办呢?

4.增加模糊查询字段
如果数据量多的情况下,将所有用户隐私信息字段分组之后都集中到一张表中,确实非常影响查询的性能,那么该如何优化呢?
可以增加模糊查询字段,还是以手机模糊查询为例
我们可以在用户表中在手机号旁边增加一个encrypt_phone字段,然后我们在保存数据的时候,将分组之后的数据拼接起来,还是以手机号为例:16602740823按每3位为一组进行拆分,拆分后的字符串为:166660602027274740408082823,这九组数据,分组之后,加密之后,用逗号分割之后拼接成这样的数据:
,sQVhAb+oiW6hLkVumIE+6g==,TrF7yedWolkcAL8+x4GlEw==,rwa99pU5dppMptqrnY01vw==,uvU9H7eGVSaOI4GXJK6nlA==,sJVLu1Rxxu3b0ZgaO9e/gw==,fypz7O6dH5284c+ZN0P5qQ==,ugNdCW4FjRNvTBuEdW08PQ==,51gRUxwSngLsUmCfqpZ2wA==,dR4ZDy1dygKQ5eppuprE/g==

以后可以直接通过sql模糊查询字段encrypt_phone了
具体sql如下:

SELECT
	id,
	username,
	phone 
FROM
	`user` 
WHERE
	encrypt_phone LIKE '%sQVhAb+oiW6hLkVumIE+6g==%'

注意这里的encrypt_value用的like

为什么分组加密之后拼接要用逗号分隔呢?
是为了防止直接字符串拼接在极端情况下,两个分组的数据原本都不满足模糊搜索条件,但拼接在一起却有一部分满足条件的情况发生,当然也可以根据实际情况,将逗号改成其他的特殊字符,此外,其他的用户隐私字段如果要实现模糊查询功能,也可以使用类似的方案

虽然本文介绍了多种加密手机号实现模糊查询功能的方案,但我们要根据实际业务场景来选择,没有最好的方案,只有最适合的

标签:encrypt,手机号,模糊,查询,字符串,加密
From: https://www.cnblogs.com/zhao-zong-yu-hai/p/18025611

相关文章

  • java练习2(四位数字进行加密)
    packagecom.shujia.zuoye;importjava.util.Scanner;/*某个公司采用公用电话传递数据,数据是四位的整数,在传递过程中是加密的,加密规则如下:每位数字都加上5,然后用和除以10的余数代替该数字,再将第一位和第四位交换,第二位和第三位交换。结果如图所示。*/publicclass加密......
  • Oracle_SQL查询语句优化
     1.应尽量避免在where子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。 2.对查询进行优化,应尽量避免全表扫描,首先应考虑在where及orderby涉及的列上建立索引。 3.应尽量避免在where子句中对字段进行null值判断,否则将导致引擎放弃使用索引而进行......
  • SQL查询数据,要求日期不间断,没有数据的日期显示0
    <selectid="getTaskPublish"resultType="java.util.Map">SELECTcount(u.id)AScount,s.dateFROM(SELECTdate_add(#{date},INTERVAL@i:=@i+1DAY)ASdateF......
  • Studio 3T 2024.1 (macOS, Linux, Windows) - MongoDB 的专业 GUI、IDE 和 客户端,支持
    Studio3T2024.1(macOS,Linux,Windows)-MongoDB的专业GUI、IDE和客户端,支持自然语言查询TheprofessionalGUI,IDEandclientforMongoDB请访问原文链接:Studio3T2024.1(macOS,Linux,Windows)-MongoDB的专业GUI、IDE和客户端,支持自然语言查询,查看最新版......
  • collection标签多条件查询
    场景:要查的数据在两个表,并且这个两个表为一对多关系。eg:以上为我最终要得到的数据实体,现在要开始查这些数据思路:先查【一对多】中的【一】这张表基本信息,其次查【多】中你要进行多条件筛选的这些条件字段代码:1、查基本信息<selectid="selectByDeviceCode"resultMap="map">......
  • Oracle递归授权view底层依赖表查询权限存储过程
    createorreplaceproceduresys.grant_view_base_table_access(p_accessownerVARCHAR2,p_vownerVARCHAR2,p_vnameVARCHAR2)--RETURNnumberasv_accessownerVARCHAR2(200):=trim(upper(p_accessowner));v_ownerVARCHAR2(200):=trim(upper(p_vowner));v_nameVARCHAR......
  • Qt 使用QCryptographicHash做简单的数据加密
    在编写程序的时候经常会使用到一些加密的方法,在Qt中,提供了一些常用的加密方法:Md4,Md5,Sha1,Sha224,Sha256,Sha384,Sha512,Sha3_224,Sha3_256,Sha3_384,Sha3_512,如果我们需要使用这些加密方法时,可以直接使用Qt中的QCryptographicHash类进行加密。1#include<QCryptographic......
  • Qt 哈希加密 QCryptographicHash
    QCryptographicHash类提供了生成密码散列的方法。该类可以用于生成二进制或文本数据的加密散列值。目前支持MD4、MD5、SHA-1、SHA-224、SHA-256、SHA-384和SHA-512。共有类型枚举QCryptographicHash::Algorithm:公共函数voidaddData(constchar*data,intlength)......
  • 查询 MMDB 数据库
    importjava.io.File;importjava.net.InetAddress;importcom.fasterxml.jackson.databind.JsonNode;importcom.maxmind.db.Reader;publicclassIpDemo{publicstaticvoidmain(String[]args)throwsException{Filedatabase=newFile("re......
  • ef 中无法提前使用 linq 查询的解决办法?
    ef中有如下的查询条件,在.ToList之后它可以被翻译为sql,但在.ToList之前不行,我该如何写出等价可被翻译的.Where条件?.Where(x=>selectedBookItems.Any(y=>y.BookID==x.BookID)).Where(x=>etSearchTitle.Text.Split(newString[]{""},Str......