AES加密后的数据还能 LIKE 查询吗?数据库密文搜索的 7 种实现方案
2026/7/14 19:28:10 网站建设 项目流程

一、背景介绍:为什么 AES 加密后无法直接进行 LIKE 查询?

在传统的数据库设计中,像手机号、身份证、银行卡等高敏感数据,通常会采用标准对称加密算法(如AES-128-ECBAES-256-CBC)进行密文存储,以满足数据合规(如等保、网络安全法)并防止数据库被物理拖库后明文泄露。

然而,一旦数据被 AES 加密,就会引入一个经典的工程痛点:加密算法彻底破坏了明文的连续性和特征性。

1. 雪崩效应(Avalanche Effect)

标准加密算法追求“明文微小的变化导致密文巨大的差异”。例如:

  • 明文:18123456789密文:U2FsdGVkX19...

  • 明文:18123456780密文:bWRmY2Z4Z2...

仅仅最后一位数字的变化,产生的密文长相天差地别,并且密文字符间没有任何规律。

2. 传统LIKE检索失效

当我们在数据库中执行WHERE phone LIKE '%2345%'时,数据库底层需要去密文列里寻找包含2345加密后的特征。但由于雪崩效应,明文中连续的2345在加密后散落在密文的不同块中,变成了完全不可读、不连续的乱码。

这意味着,如果直接对密文进行LIKE查询,数据库既无法通过 B+ 树索引精确定位,也无法通过字符串匹配过滤。如果强行在内存中把每条数据解密再做LIKE,会直接引发全表扫描,在百万级以上的数据量下,会导致 CPU 瞬时飙升到 100%,系统直接崩溃。

因此,为了在“密文安全性”“模糊查询性能”之间找到平衡,业界演进出了以下 7 种不同的解决思路。

二、 数据库密文搜索方案全景对比矩阵

方案名称核心机制最佳适用场景安全性查询性能研发/落地成本

1. 辅助搜索字段

(N-Gram 提取)

明文切片 + Hash 拼接 + LIKE 匹配

短且格式固定的敏感字段

(手机号、身份证、银行卡)

⭐⭐⭐

(防拖库,但有被撞库风险)

⭐⭐⭐⭐

(依赖 LIKE 优化)

极低

只需单表加字段,MySQL 原生支持

2. Hash Token 索引

(倒排关联表)

NLP 分词 + Hash 提取 + 等值精确匹配

非固定长度的中短文本

(姓名、地址、企业名称)

⭐⭐⭐⭐

(单向 Hash 安全性高)

⭐⭐⭐⭐⭐

(100% 榨干 B+ 树索引)

中等

需维护索引表,有写入放大

3. ES 密文搜索

(专业检索引擎)

数据异构同步 + ES 密文分词建立倒排索引

高并发、海量数据、大文本检索

(长文备注、全局全文搜索)

⭐⭐⭐⭐

(系统边界隔离)

⭐⭐⭐⭐⭐

(百万级毫秒响应)

需引入中间件,维护数据一致性

4. 透明加密

(TDE / 插件)

引擎/插件层拦截,落盘加密,内存解密

遗留老系统改造、防物理拔盘

(代码“零侵入”合规改造)

⭐⭐

(防不住内鬼或 DB 账号泄露)

⭐⭐

(全表扫描会致 CPU 飙升)

极低

业务代码 0 修改

5. 可搜索加密

(SSE)

客户端生成陷门,服务端密文态直接匹配

高密级云端隐私保护

(网盘、医疗电子病历云托管)

⭐⭐⭐⭐⭐

(绝对的数据安全)

⭐⭐⭐

(仅支持精确/布尔匹配)

极高

缺乏成熟开源组件,落地难

6. 保序加密

(OPE)

加密后密文字典序与明文保持一致

范围筛选与排序

(薪资>、年龄BETWEEN

(易遭频率分析/已知明文攻击)

⭐⭐⭐⭐

(支持原生索引及排序)

中等

需引入特定算法库

7. 同态加密

(FHE)

密文直接参与数学多项式计算

跨机构数据可用不可见

(政企联合计算、隐私求交)

⭐⭐⭐⭐⭐

(密码学理论的安全终局)

(比明文慢数万倍)

无法在线应用

目前仅存在于实验室或离线计算

三、 七大方案具体实现与操作指南

方案1:辅助搜索字段(N-Gram 滑动窗口)

推荐指数:⭐⭐⭐⭐⭐

核心思想:密文保存真实数据。数据写入时利用滑动窗口算法(N-Gram)将明文切分成固定长度的特征子串,经过 Hash 处理后拼接存入额外的“辅助字段”。

使用场景:长度较短且固定的敏感字段模糊查询。如:手机号、身份证号、银行卡号

具体实现的操作:

1、数据库设计:表中增加phone_secret(存 AES 密文)和phone_sign(存辅助 Hash 字符串)。

2、Java 写入处理:以手机号18123456789为例,设定 3 位滑动切分。

  • 切分明文:得到181,812,123...789
  • 加盐 Hash:对每个切片进行 MD5 计算,得到MD5(181),MD5(812)等。
  • 拼接存储:用逗号包裹拼接,存入phone_sign字段:,hash1,hash2,hash3,

3、Java 查询处理:用户输入181

  • 后端计算MD5(181),并拼接成,hash1,

4、SQL 执行

SELECT id, phone_secret FROM users WHERE phone_sign LIKE '%,hash1,%';

优缺点:

  • 优点:兼顾性能与安全,实现简单,直接利用 MySQL 的LIKE机制。

  • 缺点:无法支持比 N-Gram 窗口更短的关键词(如搜 2 位数会失效);大文本会导致辅助字段极度膨胀。

方案2:Hash Token 搜索索引(倒排关联表)

推荐指数:⭐⭐⭐⭐⭐

核心思想:利用 NLP 分词器将明文切分为有实际意义的词元(Token),对 Token 计算 Hash,并将 Hash 值提取到一张独立的“索引中间表”中,实现绝对精确匹配。

使用场景:长度不一、包含业务语义的中短文本。如:用户真实姓名、企业名称、短地址。

具体实现的操作:

1、数据库设计:主表users只存idname_secret。新建关联索引表user_name_index (user_id, token_hash)并对token_hash建立 B+ 树索引。

2、Java 写入处理:以姓名“张三丰”为例。

  • 分词工具(如 HanLP):切分为,,,张三,三丰,张三丰
  • Hash 映射:将上述 6 个词进行 SHA256 计算,得到 6 个 Hash 值。
  • 落库:主表存入 AES 密文;索引表批量插入 6 条记录,绑定主表id

3、查询与 SQL 执行:用户输入“张三”,后端计算得到hash_张三

-- 完全抛弃 LIKE,转化为极致性能的精确连表/子查询 SELECT u.id, u.name_secret FROM users u JOIN user_name_index idx ON u.id = idx.user_id WHERE idx.token_hash = 'hash_张三';

优缺点:

  • 优点:安全性极高,查询彻底转化为等值匹配(=),可 100% 榨干 B+ 树索引性能,不再有全表扫描的风险。

  • 缺点:写放大严重,一条数据可能对应几十条索引记录,占用较多存储空间。

方案3:Elasticsearch 密文搜索

推荐指数:⭐⭐⭐⭐⭐

核心思想:数据库彻底剥离模糊查询职责,仅做加密存储与事务。将文本同步至专业的全文检索引擎(ES),在 ES 端做分词并存储词元的 Hash 或确定性加密(DET)密文。

使用场景:高并发、海量数据、大文本的复杂检索引擎。如:文章内容、长篇备注、聊天记录的全局搜索。

具体实现的操作:

1、架构协同:通过 Canal 或 MQ 监听 MySQL binlog,将数据异步同步给中台服务。

2、密文索引构建:中台服务获取到明文大段落,使用 IK 分词器进行细粒度切词,将切出来的几百个词全部执行确定性加密(DET,同明文同密文),将这些密文词条推入 ES 构建倒排索引。

3、查询流转

  • 客户端搜索关键词“苹果”。
  • 后端对“苹果”执行同样的 DET 加密,得到密文_Apple
  • 去 ES 查询match: { content: "密文_Apple" },获取匹配的文档 ID 列表。
  • 拿 ID 列表回查 MySQL,获取完整 AES 密文并在前端解密。

优缺点:

  • 优点:降维打击,完美解决大文本密文搜索、多条件复合筛选、高并发等所有性能问题。
  • 缺点:引入了分布式组件,架构极度复杂,需要处理数据最终一致性问题。

方案4:数据库加密插件 / 透明加密 TDE

推荐指数:⭐⭐⭐⭐

核心思想:利用数据库底层的能力,数据在写入磁盘前被引擎层拦截并加密,读取到内存前被解密。对上层 Java 代码和 SQL 完全透明。

使用场景:遗留老系统改造、代码“零侵入”合规需求、防物理硬盘丢失/拖库

具体实现的操作:

1、基于 TDE(以 MySQL 企业版为例)

  • DBA 配置 Keyring 插件,生成主密钥(Master Key)。
  • 执行ALTER TABLE users ENCRYPTION='Y';
  • Java 代码:无需任何修改。正常的SELECT * FROM users WHERE name LIKE '%张三%'照跑不误,数据库在内存中自动完成解密过滤。

2、基于函数插件(如 PostgreSQL 的 pgcrypto)

  • 在 DB 安装扩展:CREATE EXTENSION pgcrypto;
  • Java 的 Mybatis 拦截器自动在 SQL 层面包裹加解密函数:
SELECT * FROM users WHERE pgp_sym_decrypt(name_secret, '密钥') LIKE '%张三%';

优缺点:

  • 优点:研发效能极高,业务代码几乎零改动。
  • 缺点:TDE 只能防“拔硬盘”,防不住拥有 DB 账密的黑客(连上数据库直接查出来的就是明文);插件函数查询会导致索引失效,引发严重的 CPU 开销。

方案5:可搜索加密 SSE (Searchable Symmetric Encryption)

推荐指数:⭐⭐⭐

核心思想:一种高阶密码学协议。客户端在本地构建“加密的安全倒排索引”传给服务器,搜索时生成“陷门(Trapdoor)”,服务器利用陷门在索引上做数学匹配,全过程服务器不接触明文和密钥。

使用场景:极致的云端隐私保护。如:公有云个人网盘搜索、高密级医疗电子病历系统(防范云厂商内部作恶)。

具体实现的操作:

1、客户端构建(本地):提取文档关键词(如“病历”),利用客户端持有的密钥生成密文索引结构(如字典树或哈希映射表),并将原始文档用 AES 加密。将两者同时上传到不受信任的服务器。

2、生成陷门(本地):医生想要检索“病历”,客户端使用密钥对“病历”运算,生成一段随机乱码特征(陷门 Token)。

3、服务器匹配(云端):服务器运行定制的 SSE 匹配算法,将传入的 Token 放入密文索引中进行校验。如果算法返回 True,则将对应的密文文档返回。

优缺点:

  • 优点:实现理论上的绝对安全(Data in Use 状态下的安全)。
  • 缺点:工业界成熟度低,缺乏开源中间件。目前主流 SSE 仅支持“精确相等”测试,对包含通配符的任意模糊查询支持度极差。

方案6:保序加密 OPE (Order-Preserving Encryption)

推荐指数:⭐⭐

核心思想:特殊的加密算法,保证加密后密文的字典序与明文一致(明文 A < B,密文必定 E(A) < E(B))。

使用场景:密文状态下的范围检索、排序、分页。如:薪资分布、年龄范围、注册时间过滤

具体实现的操作:

1、引入 OPE 算法库(如基于 Boldyreva 算法的密码包)。

2、Java 写入处理:系统插入员工年龄25,使用 OPE 密钥加密得到一串看似随机但保序的数字(如8472),存入age_ope字段。

3、Java 与 SQL 查询:前端请求查询“年龄在 20 到 30 岁之间的员工”。

  • 后端对 20 进行 OPE 加密得5011
  • 后端对 30 进行 OPE 加密得9980
  • SQL 执行原生的 BETWEEN 查询(由于保序特性,依然能走 B+ 树索引):
SELECT * FROM employees WHERE age_ope BETWEEN 5011 AND 9980;

优缺点:

  • 优点:无缝衔接关系型数据库的范围过滤(> / < / BETWEEN)和ORDER BY,支持原生索引。
  • 缺点:由于保留了顺序特征,它容易遭受“已知明文攻击”或“频率分析攻击”(黑客通过统计密文的分布就能猜出大体明文),不能用于极高机密数据的保护,且无法实现字符串的 LIKE 模糊匹配

方案7:同态加密 Homomorphic Encryption

推荐指数:

核心思想:密码学的圣杯。允许对密文直接进行复杂的数学代数运算,运算的结果解密后,等价于对明文进行同样操作的结果。

使用场景:跨机构的数据联合计算(可用不可见)。如:政企联合数据分析、跨银行反洗钱特征匹配

具体实现的操作:

1、引入 FHE 框架:使用开源的全同态加密库(如 Microsoft SEAL 或 IBM HElib)。

2、多项式转化:由于 FHE 只支持加法和乘法,如果要实现“字符串模糊匹配”,必须在算法层面将 ASCII 字符比对转化为复杂的数学多项式运算。

3、服务器计算:客户端将查询词加密发送给服务器。服务器(如配置了 GPU 集群的节点)使用 FHE 乘法和加法,将数据库里的密文与查询密文进行逐位运算,得出一条“匹配度评分密文”。

4、返回解密:客户端拿到评分密文,使用私钥解密,若结果为 1 则表示该行数据符合搜索条件。

优缺点:

  • 优点:终极天花板级别的安全保障,数据流转、计算的每一个环节都没有暴露的可能。
  • 缺点目前绝无可能用于主流数据库的日常搜索。全同态加密会让数据体积膨胀上百倍,且一次简单的比对可能需要耗费数分钟至数小时的 CPU 算力,根本无法满足毫秒级的在线业务(OLTP)需求。

四、 总结与架构选型决策树

  • 如果你是老系统紧急合规改造,动不了 Java 代码,且数据量不大(几万到十几万条),就选【方案 4:透明加密 TDE】,DBA 两个命令搞定。

  • 如果你要加密的是手机号、身份证、银行卡,且使用的是常规的MySQL数据库,就选【方案 1:辅助搜索字段(N-Gram 滑动窗口)】。只需要单表加一个拼接 Hash 字段,开发成本极低。

  • 如果你要加密的是用户姓名、地址、企业名称,并且追求百万级数据下的查询性能,就选【方案 2:Hash Token 搜索索引】。单独建一张索引表存单字或双字的词元 Hash,用=代替LIKE,100% 走 B+ 树索引。

  • 如果你本身就是大厂的大型高并发分布式系统,搜索的是大段文本(如聊天记录、客服备注),且团队本来就有 ES 集群,不要犹豫,就选【方案 3:Elasticsearch 密文搜索】。这是大型互联网系统唯一的正确解法。

  • 至于方案 5(SSE)、方案 6(OPE)、方案 7(同态加密),除非你的项目是国家级高密级科研项目、极度敏感的医疗病历云托管、或者金融机构间可用不可见的数据沙箱合作,否则在日常的商业 Web 业务中,一律不建议尝试落地(性能或安全性总有一个在开玩笑)。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询