【JAVA】数据库加密字段搜索方案
今天看到一篇文章,讲到加密字段的模糊查询,看到这个标题的时候心里还没有太明确的答案,怀着学习的心态看完了整篇文章,然后又查阅了很多文章都没有具体实现代码片断,于是乎就试一下!
大致分为三类做法,如下所示:
- 沙雕做法(不动脑思考直男的思路,只管实现功能从不深入思考问题)
- 常规做法(思考了查询性能问题,也会使用一些存储空间换性能等做法)
- 超神做法(比较高端的做法从算法层面上思考)
我们直接用常规做法,对密文数据进行分词组合,将分词组合的结果集分别进行加密,然后存储到扩展列,原来阿里拼多多京东都是这么干的,查询时通过key like '%partial%'
直接上代码:
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
/**
* @author 小菜鸟
*/
public class EncryptTool {
// 算法类型
public static final String DES = "DES";
// 密钥
public static final String SECRET_KEY = "12345678";
// 模糊查询字段全文
public static final String encryptString = "guangyi";
// 所有分词
public static final String[] partialStrs = new String[] {"guan", "uang", "angy", "ngyi", "guang", "uangy", "angyi", "guangy", "uangyi", "guangyi"};
public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
// 搜索条件
System.out.println(search("guan")); // true
System.out.println(search("q1")); // false
System.out.println(search("uanga")); // false
System.out.println(search("uangy")); // true
}
/**
* 拿到全文分段加密后的汇总字段
* @return
* @throws NoSuchPaddingException
* @throws IllegalBlockSizeException
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
* @throws BadPaddingException
* @throws InvalidKeyException
*/
public static String getEncryptString() throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, InvalidKeySpecException, BadPaddingException, InvalidKeyException {
StringBuffer encryptedStr = new StringBuffer();
for (String partialS : partialStrs) {
encryptedStr.append(desEncode(partialS));
}
return encryptedStr.toString();
}
/**
* 模拟数据库 like 搜索
* @param sStr
* @return
* @throws NoSuchPaddingException
* @throws IllegalBlockSizeException
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
* @throws BadPaddingException
* @throws InvalidKeyException
*/
public static boolean search(String sStr) throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, InvalidKeySpecException, BadPaddingException, InvalidKeyException {
return getEncryptString().contains(desEncode(sStr));
}
/**
* 加密算法
* @param encryptString
* @return
* @throws NoSuchPaddingException
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws InvalidKeySpecException
* @throws IllegalBlockSizeException
* @throws BadPaddingException
*/
public static String desEncode(String encryptString) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException {
SecretKeyFactory des = SecretKeyFactory.getInstance(DES);
SecretKey secretKey = des.generateSecret(new DESKeySpec(SECRET_KEY.getBytes()));
Cipher cipher = Cipher.getInstance(DES);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return new String(Base64.getEncoder().encode(cipher.doFinal(encryptString.getBytes())));
}
}
参考:
https://mp.weixin.qq.com/s/f4GMXXYxufRG9Op0Z2VZ8A
路慢慢其休远羲,吾将上下而求所

浙公网安备 33010602011771号