引入依赖
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.4</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.22</version>
</dependency>
<!-- 需要根据自己的jdk版本下载对应的依赖,地址:https://mvnrepository.com/artifact/org.bouncycastle -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.56</version>
</dependency>
工具类
package top.zhoujb.tools.encrytp;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import lombok.extern.slf4j.Slf4j;
import java.security.KeyPair;
/**
* @description: 国密算法 sm2 加密、解密相关工具类
* @create: 2023/02/10 16:41
*/
@Slf4j
public class Sm2Utils {
/**
* 公钥
*/
private static final String PUBLIC_KEY = "publicKey";
/**
* 私钥
*/
private static final String PRIVATE_KEY = "privateKey";
/**
* 加密算法
*/
private static final String ALGORITHM = "SM2";
/**
* 实例化 sm2
* @return
*/
private static SM2 initSm2(String privateKey, String publicKey) {
Assert.isTrue(StrUtil.isAllNotBlank(privateKey, publicKey), () -> new RuntimeException("实例化SM2时公钥和密钥不能为空"));
int keySize = 1024;
KeyPair privateKeyPair = SecureUtil.generateKeyPair(ALGORITHM, keySize, StrUtil.bytes(privateKey));
KeyPair publicKeyPair = SecureUtil.generateKeyPair(ALGORITHM, keySize, StrUtil.bytes(publicKey));
return SmUtil.sm2(privateKeyPair.getPrivate().getEncoded(), publicKeyPair.getPublic().getEncoded());
}
/**
* sm2加密(加密失败返回原值)
* @param str
* @return
*/
public static String encrypt(String str) {
return encryptFailToDefault(str, str);
}
/**
* sm2解密(加密失败返回原值)
* @param encryptStr
* @return
*/
public static String decrypt(String encryptStr) {
return decryptFailToDefault(encryptStr, encryptStr);
}
/**
* sm2加密(加密失败返回指定的默认值)
* @param str
* @return
*/
public static String encryptFailToDefault(String str, String defaultValue) {
try {
// 公钥加密,私钥解密
return initSm2(PUBLIC_KEY, PRIVATE_KEY).encryptBcd(str, KeyType.PublicKey, CharsetUtil.CHARSET_UTF_8);
} catch (Exception e) {
log.error("加密 字符串:【{}】失败,将返回默认值:【{}】,错误详情:", str, defaultValue, e);
return defaultValue;
}
}
/**
* sm2解密(加密失败返回指定的默认值)
* @param encryptStr
* @return
*/
public static String decryptFailToDefault(String encryptStr, String defaultValue) {
try {
// 公钥加密,私钥解密
return initSm2(PRIVATE_KEY, PUBLIC_KEY).decryptStrFromBcd(encryptStr, KeyType.PrivateKey, CharsetUtil.CHARSET_UTF_8);
} catch (Exception e) {
log.error("解密 字符串:【{}】失败,将返回默认值:【{}】,错误详情:", encryptStr, defaultValue, e);
return defaultValue;
}
}
/**
* 判断字符串是否已经加密
* @param str
* @return
*/
public static boolean hasEncrypt(String str) {
if (StrUtil.isBlank(str)) {
return false;
}
// 解密成功及视为已经加密,解密失败即视为非加密数据(解密失败会返回原数据)
return !StrUtil.equals(str, decrypt(str));
}
}
测试样例
@Test
public void test() {
// 加密测试
String str = "123456";
String encryptStr = Sm2Utils.encrypt(str);
// 结果:04C43908C3B100127FE70C8BEF62C8B55D50E4D9E93513C594AD404E1A59D0C0F1FCFB397B248BEEB01DB83F7D8DE0F19C323733394EFC3E9EB8A6E501A7B58FA5D54D145D10490BB426815F787E81B0B2D193343D7779FC7CA24FEB11DC83EFA5EC6607347BE5
System.out.println("encryptStr = " + encryptStr);
// 解密测试
String decryptStr = Sm2Utils.decrypt(encryptStr);
// 结果:123456
System.out.println("decryptStr = " + decryptStr);
// 是否加密判断
str = encryptStr;
// 结果:true
System.out.println("是否时加密后的字符串:" + Sm2Utils.hasEncrypt(encryptStr));
str = "随意字符串";
// 结果:false
System.out.println("是否时加密后的字符串:" + Sm2Utils.hasEncrypt(str));
}
参考连接
hutool国密算法工具-SmUtil