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