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

加密,手机号,如何,模糊,查询 · 浏览次数 : 11

小编点评

1.用户表中增加一个encrypt_phone字段,存储用户的加密手机号码。 2.在保存数据的时候,将分组之后的数据拼接起来。 3.在查询数据的时候,使用like模糊搜索,将加密手机号码进行模糊搜索。 4.使用逗号分割,将多个分组的数据拼接起来。 5.在进行模糊搜索的时候,要注意对数据类型进行处理,以确保模糊搜索的结果准确。 6.根据实际业务场景,选择最合适的方案,实现模糊搜索功能。

正文

前言

前几天,知识星球中有位小伙伴,问了我一个问题:加密的手机号如何模糊查询?

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

很早之前,CSDN遭遇了SQL注入,导致了600多万条明文保存的用户信息被泄。

因此,我们在做系统设计的时候,要考虑要把用户的隐私信息加密保存。

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

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

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

比如加密前的字符串:苏三说技术,使用密钥:123,生成加密后的字符串为:U2FsdGVkX1+q7g9npbydGL1HXzaZZ6uYYtXyug83jHA=

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

比如:假设查询苏三关键字,加密后的字符串是:U2FsdGVkX19eCv+xt2WkQb5auYo0ckyw

上面生成的两个加密字符串差异看起来比较大,根本没办法直接通过SQL语句中的like关键字模糊查询。

那我们该怎么实现加密的手机号的模糊查询功能呢?

1 一次加载到内存

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

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

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

还有另外一个问题是:数据一致性问题。

如果用户修改了手机号,数据库更新成功了,需要同步更新内存中的缓存,否则用户查询的结果可能会跟实际情况不一致。

比如:数据库更新成功了,内存中的缓存更新失败了。

或者你的应用,部署了多个服务器节点,有一部分内存缓存更新成功了,另外一部分刚好在重启,导致更新失败了。

该方案不仅可能会导致应用服务器出现OOM问题,也可能会导致系统的复杂度提升许多,总体来说,有点得不偿失。

2 使用数据库函数

既然数据库中保存的是加密后的字符串,还有一种方案是使用数据库的函数解密。

我们可以使用MySQL的DES_ENCRYPT函数加密,使用DES_DECRYPT函数解密:

SELECT 
DES_DECRYPT('U2FsdGVkX1+q7g9npbydGL1HXzaZZ6uYYtXyug83jHA=', '123'); 

应用系统重所有的用户隐私信息的加解密都在MySQL层实现,不存在加解密不一致的情况。

该方案中保存数据时,只对单个用户的数据进行操作,数据量比较小,性能还好。

但模糊查询数据时,每一次都需要通过DES_DECRYPT函数,把数据库中用户某个隐私信息字段的所有数据都解密了,然后再通过解密后的数据,做模糊查询。

如果该字段的数据量非常大,这样每次查询的性能会非常差。

3 分段保存

我们可以将一个完整的字符串,拆分成多个小的字符串。

以手机号为例:18200256007,按每3位为一组,进行拆分,拆分后的字符串为:182,820,200,002,025,256,560,600,007,这9组数据。

然后建一张表:

CREATE TABLE `encrypt_value_mapping` (
  `id` bigint NOT NULL COMMENT '系统编号',
  `ref_id` bigint NOT NULL COMMENT '关联系统编号',
  `encrypt_value` varchar(255) NOT NULL COMMENT '加密后的字符串'
) ENGINE=InnoDB  CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='分段加密映射表'

这张表有三个字段:

  • id:系统编号。
  • ref_id:主业务表的系统编号,比如用户表的系统编号。
  • encrypt_value:拆分后的加密字符串。

用户在写入手机号的时候,同步把拆分之后的手机号分组数据,也一起写入,可以保证在同一个事务当中,保证数据的一致性。

如果要模糊查询手机号,可以直接通过encrypt_value_mapping的encrypt_value模糊查询出用户表的ref_id,再通过ref_id查询用户信息。

具体sql如下:

select s2.id,s2.name,s2.phone 
from encrypt_value_mapping s1
inner join `user` s2 on s1.ref_id=s2.id
where s1.encrypt_value = 'U2FsdGVkX19Se8cEpSLVGTkLw/yiNhcB'
limit 0,20;

这样就能轻松的通过模糊查询,搜索出我们想要的手机号了。

注意这里的encrypt_value用的等于号,由于是等值查询,效率比较高。

注意:这里通过sql语句查询出来的手机号是加密的,在接口返回给前端之前,需要在代码中统一做解密处理。

为了安全性,还可以将加密后的明文密码,用*号增加一些干扰项,防止手机号被泄露,最后展示给用户的内容,可以显示成这样的:182***07

4 其他的模糊查询

如果除了用户手机号,还有其他的用户隐私字段需要模糊查询的场景,该怎么办?

我们可以将encrypt_value_mapping表扩展一下,增加一个type字段。

该字段表示数据的类型,比如:1.手机号 2.身份证 3.银行卡号等。

这样如果有身份证和银行卡号模块查询的业务场景,我们可以通过type字段做区分,也可以使用这套方案,将数据写入到encrypt_value_mapping表,最后根据不同的type查询出不同的分组数据。

如果业务表中的数据量少,这套方案是可以满足需求的。

但如果业务表中的数据量很大,一个手机号就需要保存9条数据,一个身份证或者银行卡号也需要保存很多条数据,这样会导致encrypt_value_mapping表的数据急剧增加,可能会导致这张表非常大。

最后的后果是非常影响查询性能。

那么,这种情况该怎么办呢?

5 增加模糊查询字段

如果数据量多的情况下,将所有用户隐私信息字段,分组之后,都集中到一张表中,确实非常影响查询的性能。

那么,该如何优化呢?

答:我们可以增加模糊查询字段。

还是以手机模糊查询为例。

我们可以在用户表中,在手机号旁边,增加一个encrypt_phone字段。

CREATE TABLE `user` (
  `id` int NOT NULL,
  `code` varchar(20)  NOT NULL,
  `age` int NOT NULL DEFAULT '0',
  `name` varchar(30) NOT NULL,
  `height` int NOT NULL DEFAULT '0',
  `address` varchar(30)  DEFAULT NULL,
  `phone` varchar(11) DEFAULT NULL,
  `encrypt_phone` varchar(255)  DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='用户表'

然后我们在保存数据的时候,将分组之后的数据拼接起来。

还是以手机号为例:

18200256007,按每3位为一组,进行拆分,拆分后的字符串为:182,820,200,002,025,256,560,600,007,这9组数据。

分组之后,加密之后,用逗号分割之后拼接成这样的数据:,U2FsdGVkX19Se8cEpSLVGTkLw/yiNhcB,U2FsdGVkX1+qysCDyVMm/aYXMRpCEmBD,U2FsdGVkX19oXuv8m4ZAjz+AGhfXlsQk,U2FsdGVkX19VFs60R26BLFzv5nDZX40U,U2FsdGVkX19XPO0by9pVw4GKnGI3Z5Zs,U2FsdGVkX1/FIIaYpHlIlrngIYEnuwlM,U2FsdGVkX19s6WTtqngdAM9sgo5xKvld,U2FsdGVkX19PmLyjtuOpsMYKe2pmf+XW,U2FsdGVkX1+cJ/qussMgdPQq3WGdp16Q。

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

select id,name,phone
from user where encrypt_phone like '%U2FsdGVkX19Se8cEpSLVGTkLw/yiNhcB%'
limit 0,20;

注意这里的encrypt_value用的like

这里为什么要用逗号分割呢?

答:是为了防止直接字符串拼接,在极端情况下,两个分组的数据,原本都不满足模糊搜索条件,但拼接在一起,却有一部分满足条件的情况发生。

当然你也可以根据实际情况,将逗号改成其他的特殊字符。

此外,其他的用户隐私字段,如果要实现模糊查询功能,也可以使用类似的方案。

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

 

最后欢迎大家加入苏三的知识星球【Java突击队】,一起学习。

星球中有很多独家的干货内容,比如:Java后端学习路线,分享实战项目,源码分析,百万级系统设计,系统上线的一些坑,MQ专题,真实面试题,每天都会回答大家提出的问题,免费修改简历,免费回答工作中的问题。

星球目前开通了9个优质专栏:技术选型、系统设计、踩坑分享、工作实战、底层原理、Spring源码解读、痛点问题、高频面试题 和 性能优化。

 

 

加入星球如果不满意,3天内包退。

 

与加密的手机号,如何模糊查询?相似的内容:

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

前言 前几天,知识星球中有位小伙伴,问了我一个问题:加密的手机号如何模糊查询? 我们都知道,在做系统设计时,考虑到系统的安全性,需要对用户的一些个人隐私信息,比如:登录密码、身份证号、银行卡号、手机号等,做加密处理,防止用户的个人信息被泄露。 很早之前,CSDN遭遇了SQL注入,导致了600多万条明

4.1 应用层Hook挂钩原理分析

InlineHook 是一种计算机安全编程技术,其原理是在计算机程序执行期间进行拦截、修改、增强现有函数功能。它使用钩子函数(也可以称为回调函数)来截获程序执行的各种事件,并在事件发生前或后进行自定义处理,从而控制或增强程序行为。Hook技术常被用于系统加速、功能增强、等领域。本章将重点讲解Hook是如何实现的,并手动封装实现自己的Hook挂钩模板。首先我们来探索一下Hook技术是如何实现的,如下

4.2 Inline Hook 挂钩技术

InlineHook 是一种计算机安全编程技术,其原理是在计算机程序执行期间进行拦截、修改、增强现有函数功能。它使用钩子函数(也可以称为回调函数)来截获程序执行的各种事件,并在事件发生前或后进行自定义处理,从而控制或增强程序行为。Hook技术常被用于系统加速、功能增强、开发等领域。本章将重点讲解Hook是如何实现的,并手动封装实现自己的Hook挂钩模板。

手动实现BERT

本文重点介绍了如何从零训练一个BERT模型的过程,包括整体上BERT模型架构、数据集如何做预处理、MASK替换策略、训练模型和保存、加载模型和测试等。 一.BERT架构 BERT设计初衷是作为一个通用的backbone,然后在下游接入各种任务,包括翻译任务、分类任务、回归任务等。BERT模型架构如下

驱动开发:内核测试模式过DSE签名

微软在`x64`系统中推出了`DSE`保护机制,DSE全称`(Driver Signature Enforcement)`,该保护机制的核心就是任何驱动程序或者是第三方驱动如果想要在正常模式下被加载则必须要经过微软的认证,当驱动程序被加载到内存时会验证签名的正确性,如果签名不正常则系统会拒绝运行驱动,这种机制也被称为驱动强制签名,该机制的作用是保护系统免受恶意软件的破坏,是提高系统安全性的一种手段

博客园商业化之路-众包平台:从第一单看基于「开发任务」的定位

虽然我们一再强调我们做的是「开发任务」众包平台,还是被不少人误解为「项目」众包平台,正好我们遇到的第一单就是一个典型案例,简单发篇博文分享一下。 4月29日我们开始召集众包平台的早期合作开发者,先以手动挡方式(微信+GitLab)验证基于「开发任务」的众包模式。 在召集博文中顺带加了个小广告: 如果

Java解析微信获取手机号信息

在微信中,用户手机号的获取通常是通过微信小程序的getPhoneNumber接口来实现的。这个接口允许用户在授权后,将加密的手机号数据传递给开发者。由于隐私保护,微信不会直接提供用户的明文手机号,而是提供一个加密的手机号字符串和相应的解密密钥。 以下是一个基于Java的示例,展示了如何接收并解密从微

接口防刷!利用redisson快速实现自定义限流注解

问题: 在日常开发中,一些重要的对外接口,需要加上访问频率限制,以免造成资��损失。 如登录接口,当用户使用手机号+验证码登录时,一般我们会生成6位数的随机验证码,并将验证码有效期设置为1-3分钟,如果对登录接口不加以限制,理论上,通过技术手段,快速重试100000次,即可将验证码穷举出来。 解决思

聊一聊如何截获 C# 程序产生的日志

一:背景 1.讲故事 前段时间分析了一个dump,一顿操作之后,我希望用外力来阻止程序内部对某一个com组件的调用,对,就是想借助外力实现,如果用 windbg 的话,可以说非常轻松,但现实情况比较复杂,客户机没有windbg,也不想加入任何的手工配置,希望全自动化来处理。 真的很无理哈。。。不过这

1.14 手工插入ShellCode反弹

PE格式是 Windows下最常用的可执行文件格式,理解PE文件格式不仅可以了解操作系统的加载流程,还可以更好的理解操作系统对进程和内存相关的管理知识,而有些技术必须建立在了解PE文件格式的基础上,如文件加密与解密,病毒分析,外挂技术等,本次的目标是手工修改或增加节区,并给特定可执行程序插入一段`ShellCode`代码,实现程序运行自动反弹一个Shell会话。