这里使用的的是 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 暂不支持中文

 

 

Rot

RotN(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,因为将 技术方案 插入数据库后,再返回给前端页面显示无此问题!