【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

posted @ 2022-08-24 15:18  我是小菜鸟  阅读(724)  评论(0编辑  收藏  举报