【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
路慢慢其休远羲,吾将上下而求所