mybatis-plus中文加解密及中文模糊查询实现(多种加密算法比较)

这里使用的的是 hutool-all.jar (compile 'cn.hutool:hutool-all:5.5.2') 提供的各种加密算法,

如:Morse 莫尔斯电码,Caesar 凯撒密码(移位密码),RotN密码,PunyCode,Base32, Base62, Base64编码,

对称加密算法:AES, DES, sm4;

如果想选用国密算法,需要另外引入 bcprov-jdk15on.jar ( compile 'org.bouncycastle:bcprov-jdk15on:1.68')

对比方案如下

cn.hutool:hutool-all:5.5.2 提供的几种加密算法对比
加密算法算法介绍支持中文加密模糊查询举例
Base32使用8个ASCII字符去编码原数据中的5个字节数据
Base32比Base64多占用大约20%的空间
支持中文支持部分模糊匹配广州                    4W437ZNXTY
广州集联             
4W437ZNXT3UZXBXIQGKA
广州集联95coder 4W437ZNXT3UZXBXIQGKDSNLDN5SGK4Q
Base64使用4个ASCII字符去编码原数据中的3个字节数据
标准的Base64最后需要用=补位
支持中文支持模糊匹配广州                     5bm/5bee
广州集联              5bm/5bee6ZuG6IGU
广州集联95coder  5bm/5bee6ZuG6IGUOTVjb2Rlcg==
Base62使用了62个字符编码,包括0-9,a-z,A-Z
Base62和Base64相比唯一的区别就是少了两个特殊符号
支持中文不支持模糊匹配广州                     19iusAGNy
广州集联              1USmP5wRtBYJGfnd6
广州集联95coder  7wBSLiqTdcWmb8qpl4iqhctMO2
Morse莫尔斯电码支持中文支持模糊匹配广州           -.----..-------/-.---.---.----./
广州集联    -.----..-------/-.---.---.----./-..-.--.--...--./-........-.-.-../
PunyCode是一个根据RFC 3492标准而制定的编码系统,主要用于把域名从地方语言所采用的Unicode编码转换成为可用于DNS系统的编码。支持中文不支持模糊匹配广州                      6rtwn
广州集联               6rtwng25fx0s
广州集联95coder   95coder-ld0ni9bv42q4u7b
AesBase64对称加密算法:AES对称加密后转base64支持中文不支持模糊匹配广州                     6fpGTQhU2t1U8QmgLODoPw==
广州集联              rtsSEzZwemaSN1Lz5CRz8A==
广州集联95coder  rkByH/uxr69ijfsL/z7MvQetprbEhD321ShSsJqFEEY=
DesBase64对称加密算法:DES对称加密后转base64支持中文不支持模糊匹配广州                     tCqdqe7JR1M=
广州集联              HL9vDCaKrzohRrX6uJMt3A==
广州集联95coder  Od/k45Gnee41Ur3VIx78+26fscU98u7D
sm4对称加密算法:国密算法 sm4支持中文不支持模糊匹配广州                     cgkHwr7tjg7swcAX5f24Dw==
广州集联              W7eJ2vx/tTuihsibdD/BHw==
广州集联95coder  m1EJcqqEG4jykV5zneV1myvDr4scC43jKzFgCrm3jXc=
Caesar凯撒密码:是一种移位密码,通过移位加解密hutool 暂不支持中文  
RotRotN(rotate by N places),回转N位密码,是一种简易的替换式密码,也是过去在古罗马开发的凯撒加密的一种变体hutool 暂不支持中文  

mybatis-plus 具体使用方法介绍:

Entity-Class上添加:@TableName(value = "t_user", autoResultMap = true)  //此句主要用于查询返回的结果值解密处理

Entity-字段属性上添加:@TableField(value="name", typeHandler = Base64SecureHandler.class) //设置字段的加解密处理器
/**
 * Base64算法,支持加密字段的模糊查询;加密后的长度=中文长度*4
 * 使用方式: Entity-Class上添加:@TableName(value = "t_user", autoResultMap = true)
 *          Entity-字段属性上添加:@TableField(value="name", typeHandler = Base64SecureHandler.class)
 * @author: 95coder
 * @date: 2021/4/11 10:06
 */
public class Base64SecureHandler extends BaseTypeHandler {

    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        String columnValue = (String)parameter;
        if(StrUtil.isNotBlank(columnValue)){
            preparedStatement.setString(i, Base64.encode(columnValue));
        }
    }

    @Override
    public Object getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
        String columnValue = resultSet.getString(columnName);
        if(StrUtil.isNotBlank(columnValue)){
            return Base64.decodeStr(columnValue);
        }
        return columnValue;
    }

    @Override
    public Object getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
        String columnValue = resultSet.getString(columnIndex);
        if(StrUtil.isNotBlank(columnValue)){
            return Base64.decodeStr(columnValue);
        }
        return columnValue;
    }

    @Override
    public Object getNullableResult(CallableStatement callableStatement, int columnIndex) throws SQLException {
        String columnValue = callableStatement.getString(columnIndex);
        if(StrUtil.isNotBlank(columnValue)){
            return Base64.decodeStr(columnValue);
        }
        return columnValue;
    }
}
/**
 * 各种加密算法测试
 * @author: 95coder
 * @date: 2021/4/12 8:40
 */
public class ChineseUtil {

    //private static String text1 = "技术方案";
    private static String text1 = "广州";
    private static String text2 = "广州集联";
    private static String text3 = "广州集联95coder";

    /**
     * 支持中文:转换结果太长
     * 莫尔斯电码的编码和解码实现;参考:https://github.com/TakWolf/Java-MorseCoder
     */
    public static void testMorse(String text){
        Morse morse = new Morse();
        String encode = morse.encode(text);
        String decode = morse.decode(encode);
        //广州             -.----..-------/-.---.---.----./
        //广州集联          -.----..-------/-.---.---.----./-..-.--.--...--./-........-.-.-../
        //广州集联95CODER   -.----..-------/-.---.---.----./-..-.--.--...--./-........-.-.-../----./...../-.-./---/-.././.-./
        System.out.println("testMorse "+ encode+" , "+decode);
    }

    /**
     * 支持中文:加密后不支持模糊匹配
     * Punycode是一个根据RFC 3492标准而制定的编码系统,主要用于把域名从地方语言所采用的Unicode编码转换成为可用于DNS系统的编码
     */
    public static void testPunyCode(String text){
        String encode = PunyCode.encode(text);
        String decode = PunyCode.decode(encode);
        //广州          6rtwn
        //广州集联       6rtwng25fx0s
        //广州集联95coder   95coder-ld0ni9bv42q4u7b
        System.out.println("testPunyCode "+ encode+" , "+decode);
    }

    /**
     * 不支持中文:只支持数字+英文+符号
     * 凯撒密码实现  算法来自:https://github.com/zhaorenjie110/SymmetricEncryptionAndDecryption
     */
    public static void testCaesar(String text){
        String encode =  Caesar.encode(text, 15);
        String decode =  Caesar.decode(encode, 15);
        //广州, encode=HH, decode=zz
        //广州集联, encode=HHHH, decode=zzzz
        //广州集联95coder, encode=HHHH95KWLMZ, decode=zzzz95coder
        System.out.println("testCaesar="+text+", encode="+ encode+", decode="+decode);
    }

    /**
     * 不支持中文:只支持数字+英文+符号
     * RotN(rotate by N places),回转N位密码,是一种简易的替换式密码,也是过去在古罗马开发的凯撒加密的一种变体。
     */
    public static void testRot(String text){
        String encode =  Rot.encode13(text);
        String decode =  Rot.decode13(encode);
        //广州 , 广州
        //广州集联 , 广州集联
        //广州集联95coder  -->  广州集联28pbqre
        System.out.println("testRot "+ encode+" , "+decode);
    }

    /**
     * 支持中文:不支持加密后模糊匹配
     * Base62工具类,提供Base62的编码和解码方案
     */
    public static void testBase62(String text){
        String encode =  Base62.encode(text);
        String decode =  Base62.decodeStr(encode);
        //广州     19iusAGNy
        //广州集联  1USmP5wRtBYJGfnd6
        //广州集联95coder  7wBSLiqTdcWmb8qpl4iqhctMO2
        System.out.println("testBase62 "+ encode+" , "+decode);
    }

    /**
     * Base32工具类,提供Base64的编码和解码方案 base64编码是用64(2的6次方)个ASCII字符来表示256(2的8次方)个ASCII字符,
     * 也就是三位二进制数组经过编码后变为四位的ASCII字符显示,长度比原来增加1/3。
     */
    public static void testBase32(String text){
        String encode =  Base32.encode(text);
        String decode =  Base32.decodeStr(encode);
        //广州             4W437ZNXTY
        //广州集联          4W437ZNXT3UZXBXIQGKA
        //广州集联95coder   4W437ZNXT3UZXBXIQGKOJP5B42A26OJVMNXWIZLS
        System.out.println("testBase32 "+ encode+" , "+decode);
    }

    /**
     * 可行:idea下执行部分中文乱码:技术方案,其它基本都支持,此为idea bug
     * Base64工具类,提供Base64的编码和解码方案 base64编码是用64(2的6次方)个ASCII字符来表示256(2的8次方)个ASCII字符,
     * 也就是三位二进制数组经过编码后变为四位的ASCII字符显示,长度比原来增加1/3。
     */
    public static void testBase64(String text){
        String encode =  Base64.encode(text);
        String decode =  Base64.decodeStr(encode);
        //广州            5bm/5bee
        //广州集联         5bm/5bee6ZuG6IGU
        //广州集联95coder  5bm/5bee6ZuG6IGUOTVjb2Rlcg==
        System.out.println("testBase64 "+ encode+" , "+decode);
    }

    public static void testAesBase64(String text){
        byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded();
        String encode =  SecureUtil.aes(key).encryptBase64(text);
        String decode =  SecureUtil.aes(key).decryptStr(encode);
        //广州            6fpGTQhU2t1U8QmgLODoPw==
        //广州集联         rtsSEzZwemaSN1Lz5CRz8A==
        //广州集联95coder  rkByH/uxr69ijfsL/z7MvQetprbEhD321ShSsJqFEEY=
        System.out.println("testAesBase64 "+ encode+" , "+decode);
    }

    public static void testDesBase64(String text){
        byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.DES.getValue()).getEncoded();
        String encode =  SecureUtil.des(key).encryptBase64(text);
        String decode =  SecureUtil.des(key).decryptStr(encode);
        //广州            tCqdqe7JR1M=
        //广州集联         HL9vDCaKrzohRrX6uJMt3A==
        //广州集联95coder  Od/k45Gnee41Ur3VIx78+26fscU98u7D
        System.out.println("testDesBase64 "+ encode+" , "+decode);
    }

    public static void testSM4(String text){
        // key必须是16位
        String key="1234567890123456";
        SymmetricCrypto sm4 = SmUtil.sm4(key.getBytes());
        String encode =  sm4.encryptBase64(text);
        String decode =  sm4.decryptStr(encode);
        //广州             cgkHwr7tjg7swcAX5f24Dw==
        //广州集联          W7eJ2vx/tTuihsibdD/BHw==
        //广州集联95coder   m1EJcqqEG4jykV5zneV1myvDr4scC43jKzFgCrm3jXc=
        System.out.println("testSM4 "+ encode+" , "+decode);
    }

    public static void main(String[] args) {
        //testMorse(text1);
        //testPunyCode(text1);
        //testCaesar(text1);
        //testRot(text1);
        //testBase32(text1);
        //testBase32(text2);
        //testBase32(text3);
        //testBase62(text1);
        //testBase64(text1);
        //testAesBase64(text1);
        //testDesBase64(text1);
        testSM4(text1);
        testSM4(text2);
        testSM4(text3);
    }
}

 

最后想说一下测试中遇到的奇葩问题

本人用的是idea开发工具,在main()方法中执行加解密函数,中文(技术方案),解密后打印出来的是乱码,如下

PunyCode    执行加密得到 :2qur5eb6af6a                                解密后得到 :�?术方�?

Base32        执行加密得到 :42FIBZU4V7TJNOPGUGEA         解密后得到 : �?术方�?

Base62        执行加密得到 :1Un840vBwAuNOo9ge                  解密后得到 : �?术方�?

AesBase64  执行加密得到 :xrb3dTv4wEQacLM+OxB0eg==    解密后得到 : �?术方�?

DesBase64  执行加密得到 :3mXHySoQypTRFm9PRlGlsw==  解密后得到 : �?术方�?

SM4             执行加密得到 :LdwTgbyOA7dTZZ/envqfrQ==       解密后得到 : �?术方�?

怀疑是idea中文处理的Bug,因为将 技术方案 插入数据库后,再返回给前端页面显示无此问题!

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 在使用MyBatis-Plus进行数据加密后,进行模糊查询的方式如下: 1. 加密查询条件 在进行模糊查询之前,需要将查询条件进行加密处理,保证查询条件和数据库中存储的数据是加密的一致形式。可以使用加密算法对查询条件进行加密,然后将加密后的条件作为参数传入查询方法。 2. 添加查询条件 在MyBatis-Plus的查询方法中,可以通过Wrapper对象来添加查询条件。可以使用like方法来添加模糊查询条件,如:`.like("encrypted_column", encryptedValue)`,其中"encrypted_column"为数据库中的加密字段名,encryptedValue为加密后的查询条件值。 3. 执行模糊查询 将加密后的查询条件加入到查询方法中,执行查询操作。MyBatis-Plus会自动生成对应的SQL语句,将加密后的条件解密后,与数据库中的数据进行比较,返回符合要求的结果集。 需要注意的是,数据加密后进行模糊查询可能会存在性能问题,因为加密后的数据在查询时需要进行解密操作,而解密是一个相对耗时的过程。为了提升查询性能,可以考虑将部分常用的模糊查询条件提前进行加密并缓存,减少解密操作的次数。 总之,使用MyBatis-Plus进行数据加密后进行模糊查询,需要在查询条件加密的前提下,使用加密后的查询条件进行模糊查询操作,以获得符合要求的结果集。 ### 回答2: 在使用Mybatis-Plus进行数据加密后,进行模糊查询的方法有以下几种: 1.使用数据库原生函数: 可以使用数据库原生函数,如MySql的`like`函数实现模糊查询。在加密过程中,将待查询的关键字加密后,使用`like`函数进行模糊匹配。例如,假设对某列进行加密后,需要模糊查询包含关键字"abc"的数据,可以将"abc"加密得到"xyz",然后使用Mybatis-Plus的查询方法,拼接`like '%xyz%'`进行查询。 2.使用Mybatis-Plus的`LambdaQueryWrapper`: 可以使用Mybatis-Plus提供的`LambdaQueryWrapper`来进行模糊查询。在加密过程中,将待查询的关键字加密后,使用`like`方法进行模糊匹配。例如,假设对某列进行加密后,需要模糊查询包含关键字"abc"的数据,可以将"abc"加密得到"xyz",然后使用`like`方法进行查询。示例代码如下: ```java LambdaQueryWrapper<Entity> wrapper = new LambdaQueryWrapper<>(); wrapper.like("column_name", "xyz"); List<Entity> result = entityMapper.selectList(wrapper); ``` 3.自定义SQL查询: 如果以上方法无法满足需求,还可以使用自定义SQL语句进行模糊查询。在加密过程中,将待查询的关键字加密后,直接在SQL语句中拼接加密后的关键字。例如,假设对某列进行加密后,需要模糊查询包含关键字"abc"的数据,可以将"abc"加密得到"xyz",然后使用自定义SQL语句进行查询。示例代码如下: ```java @Select("SELECT * FROM table_name WHERE column_name LIKE CONCAT('%', #{keyword}, '%')") List<Entity> customSelect(@Param("keyword") String keyword); ``` 以上是几种常用的方法,根据具体的需求和加密方式,可以选择相应的方法进行模糊查询

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星梦天河

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值