JPA Converter加密文本时如何实现加密数据模式搜索
问题根因
你当前的模糊查询不生效是核心逻辑错误导致的:
@Convert注解实现的加解密完全在应用层JVM内执行,数据库中存储的是全字段加密后的密文,数据库侧根本不存在你SQL里写的encryption()加密逻辑,也没有对应的密钥。- 全值匹配能生效,是因为JPA在发起SQL前已经把你传入的完整明文参数加密成了整段密文,到数据库侧直接做密文等值比对,自然能匹配到结果。
- 就算你把相同的加密逻辑搬到数据库侧执行,只要你用的是带随机初始化向量(IV)的安全加密算法(比如标准AES-CBC、AES-GCM),相同明文每次加密生成的密文都完全不同;哪怕你用了无IV的确定性加密,加密是按数据块分组运算的,明文中的子串
sher对应的密文,和整段邮箱明文加密后密文中的片段也完全没有对应关系,直接拿加密后的关键字做like匹配永远不可能命中结果。
现有方案的临时适配方式
如果你的业务数据量很小(单表记录在万级以内),可以放弃数据库侧模糊查询:直接把目标字段的全量数据查询到内存中,JPA会自动通过@Convert的解密逻辑把密文转为明文,再在Java代码层面做字符串模糊匹配即可。
注意:这个方式在数据量上涨后会出现严重的性能问题,会触发全表扫描、大量网络IO和内存占用,生产环境不推荐使用。
支持加密数据模糊搜索的列级加密落地方案
- 数据库原生函数加解密
把加解密逻辑从应用层@Convert下沉到数据库侧,使用MySQL自带的AES_ENCRYPT/AES_DECRYPT函数做列级加解密:存储时调用AES_ENCRYPT(明文, 密钥)生成密文落库;模糊查询时写原生SQL执行SELECT email_id FROM customer WHERE AES_DECRYPT(email_id, 密钥) LIKE CONCAT('%', ?, '%'),在JPA中通过设置nativeQuery = true来执行这类语句。这个方案实现简单改造成本低,但查询时需要逐行解密,大表场景性能差,密钥需要传给数据库,存在密钥泄露风险。 - 分词盲索引方案
这是目前互联网行业PII字段加密搜索的通用安全方案,性能和安全性平衡最好:给需要模糊搜索的加密字段额外配套盲索引表/索引列,将明文按固定步长做滑窗分词(比如针对sherlock@xx.com,按3字符窗口滑动拆分为she/her/erl/rlo...等子串),每个子串做确定性哈希后存入索引结构;查询时把用户输入的搜索关键字按相同的窗口规则拆分、哈希,先通过索引匹配出符合条件的候选记录ID,再把候选记录拉回应用层解密后做二次精确模糊校验,过滤分词匹配带来的误报。这个方案所有模糊匹配都走索引,性能和普通明文搜索接近,密钥全程只在应用层留存,安全性高,缺点是需要额外维护索引结构,写入时需要额外计算分词哈希,有少量性能开销。 - 透明数据加密(TDE)
MySQL 8.0企业版支持TDE落盘加密,这个方案是对磁盘上的物理数据文件加密,对有合法权限的数据库连接来说看到的是明文,仅能防范物理磁盘泄露导致的数据拖库,无法防范数据库账号权限泄露风险,适合等保合规类场景。 - 可搜索加密算法
比如保序加密、同态加密类算法,这类算法目前工程化成熟度低,加解密和查询性能差,安全边界有严格限制,非特殊强安全要求场景不推荐落地。
内容的提问来源于stack exchange,提问作者sherali inamdar
相关产品推荐
相关产品推荐

