场景需求:
项目在开发过程中经常会对重要的数据进行加密存储,在加密方式下我们在数据库检索该加密数据的时候,必须用全文匹配,如果我们想用模糊匹配方式获取数据,加密后就无法满足这样的要求了。
解决方案:
1、目前市面上的几种方案:
1)暴力做法:适用于数据量小的场景
a.将所有数据加载到内存中进行解密,解密后通过程序算法来模糊匹配 将密文数据映射一份明文映射表,俗称tag表,然后模糊查询tag来关联密文数据
优点:这样做既简单又实惠
缺点:内存占用率高(AES加密的字串越长,加密的结果就越长.一个英文字母占一个字节的空间,按长度为24那么五百万数据就需要1G内存“目前数据库数据不到五万”)
b.在数据库中实现与程序一致的加解密算法,修改模糊查询条件,使用数据库加解密函数先解密再模糊查找
优点:实现成本低,开发使用成本低,只需要将以往的模糊查找稍微修改一下就可以实现
缺点:无法利用数据库的索引来优化查询
c.将密文数据映射一份明文映射表,然后模糊查询映射表来关联密文数据
优点:实现简单
缺点:不能保证明文映射表的安全
2)常规做法(折中):单独增加一列作为检索列,原密文列为解密业务使用
a.对密文数据进行分词组合,将分词组合的结果集分别进行加密,然后存储到扩展列,查询时直接加密模糊查询
优点:实现起来不算复杂,使用起来也较为简单
缺点:因为会有扩展字段存储成本会有升高
实现:链接--加密字段的模糊检索-分词加密检索实现
b、针对密文计算一个特征值用;
c、针对明文计算一个索引值
3)设计专有加密算法支持模糊检索,这个难度高。
2、互联网大厂的方案(分词法,无法具体实现细节)
大厂 | 方案详情 | 备注 |
---|---|---|
京东 | 宙斯开发者中心 | 常用文档 | AES加密方式 |
拼多多 | 拼多多 开放平台 | AES加密方式 |
阿里巴巴+淘宝 | ||
3、开源的实现:
正在上传…重新上传取消open-api-sdk-2.0-2021-10-28.jar
项目代码实现:
一、前台 需要增加限制与后台保持一致如后台分词两个字符为一组,则前台限制字符大于等于两个字符不加限制也可以后台分词时一词一组,但会增加密文的数据量 二、后台 1、代码实现 /** * 分词加密 * * @param value 分词值 * @param splitLength 分词长度 * @return */ public static String splitValueEncrypt(String value, int splitLength) { //检查参数是否合法 if (StringUtils.isBlank(value) && splitLength <= 0) { return null; } Stri ng encryptValue = ""; //获取整个字符串可以被切割成字符子串的个数 int n = (value.length() - splitLength + 1); //分词(规则:分词长度根据【splitLength】且每次分割的开始跟结束下标加一) for (int i = 0; i < n; i++) { String splitValue = value.substring(i, splitLength++); encryptValue += gainEncryptValue(splitValue); } return encryptValue; } /** * 获取加密值 * * @param value 加密值 * @return */ private static String gainEncryptValue(String value) { //我项目里用的是AES加密方式直接调用加密接口 return encrypt("1WsXNrzEOaEGfbz6bNvgd1cZT9ArcKp6FwA0iZpU/qY=", value); } 2、程序更改 所有涉及到分词加密字段的 增、改、查操作都需要调用splitValueEncrypt公共接口生成分词密文 三、数据库 模糊查询的密文字段需增加一列对应的搜索字段,用来存储相同明文分词后的密文