cn.hutool
hutool-all
5.5.8
2、代码:
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.BCUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import java.security.PrivateKey;
import java.security.PublicKey;
* 国密.
* @author lizhm
@Slf4j
public class Sm2Util {
public static String PRIVATE_KEY = "";
public static String PUBLIC_KEY = "";
private static int PUBLIC_LENGTH = 130;
* 生成公钥、私钥.
* @author lizhm
* @date 2023/2/21 16:37
* @history <author> <time> <version> <desc>
private static void genKeyPair() {
SM2 sm2 = SmUtil.sm2();
// 私钥:切记不要泄漏,真的泄露了就重新生成一下
byte[] privateKey = BCUtil.encodeECPrivateKey(sm2.getPrivateKey());
//这里默认公钥压缩 公钥的第一个字节用于表示是否压缩 02或者03表示是压缩公钥,04表示未压缩公钥
byte[] publicKey = BCUtil.encodeECPublicKey(sm2.getPublicKey());
//这里得到未压缩的公钥 byte[] publicKey = ((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false);
PRIVATE_KEY = HexUtil.encodeHexStr(privateKey);
PUBLIC_KEY = HexUtil.encodeHexStr(publicKey);
* SM2加密算法.
* @param data 加密前的明文
* @param publicKey 公钥
* @return String 加密后的密文
* @author lizhm
* @history <author> <time> <version> <desc>
public static String encrypt(String publicKey, String data) {
ECPublicKeyParameters ecPublicKeyParameters = null;
//这里需要根据公钥的长度进行加工
if (publicKey.length() == PUBLIC_LENGTH) {
//这里需要去掉开始第一个字节 第一个字节表示标记
publicKey = publicKey.substring(2);
String xhex = publicKey.substring(0, 64);
String yhex = publicKey.substring(64, 128);
ecPublicKeyParameters = BCUtil.toSm2Params(xhex, yhex);
} else {
PublicKey p = BCUtil.decodeECPoint(publicKey, SmUtil.SM2_CURVE_NAME);
ecPublicKeyParameters = BCUtil.toParams(p);
//创建sm2 对象
SM2 sm2 = new SM2(null, ecPublicKeyParameters);
// 公钥加密
return sm2.encryptBcd(data, KeyType.PublicKey);
* SM2加密算法.
* @param publicKey 公钥
* @param text 明文数据
* @return String
* @author lizhm
* @history <author> <time> <version> <desc>
public static String encrypt(PublicKey publicKey, String text) {
ECPublicKeyParameters ecPublicKeyParameters = BCUtil.toParams(publicKey);
//创建sm2 对象
SM2 sm2 = new SM2(null, ecPublicKeyParameters);
// 公钥加密
return sm2.encryptBcd(text, KeyType.PublicKey);
* SM2解密算法.
* @param cipherData 加密密文
* @param privateKey 私秘钥
* @return String 解密后的明文字符串
* @author lizhm
* @history <author> <time> <version> <desc>
public static String decrypt(String privateKey, String cipherData) {
if (StrUtil.isBlank(cipherData)) {
throw new RuntimeException("解密串为空,解密失败");
ECPrivateKeyParameters ecPrivateKeyParameters = BCUtil.toSm2Params(privateKey);
//创建sm2 对象
SM2 sm2 = new SM2(ecPrivateKeyParameters, null);
// 私钥解密
return StrUtil.utf8Str(sm2.decryptFromBcd(cipherData, KeyType.PrivateKey));
* SM2解密算法.
* @param privateKey 私钥
* @param cipherData 密文数据
* @return String
* @author lizhm
* @history <author> <time> <version> <desc>
public static String decrypt(PrivateKey privateKey, String cipherData) {
ECPrivateKeyParameters ecPrivateKeyParameters = BCUtil.toParams(privateKey);
//创建sm2 对象
SM2 sm2 = new SM2(ecPrivateKeyParameters, null);
// 私钥解密
return StrUtil.utf8Str(sm2.decryptFromBcd(cipherData, KeyType.PrivateKey));
* 私钥签名.
* @param privateKey 私钥
* @param content 待签名内容
* @return String
* @author lizhm
* @history <author> <time> <version> <desc>
public static String sign(String privateKey, String content) {
ECPrivateKeyParameters ecPrivateKeyParameters = BCUtil.toSm2Params(privateKey);
//创建sm2 对象
SM2 sm2 = new SM2(ecPrivateKeyParameters, null);
return sm2.signHex(HexUtil.encodeHexStr(content));
* 验证签名.
* @param publicKey 公钥
* @param content 待签名内容
* @param sign 签名值
* @return boolean
* @author lizhm
* @history <author> <time> <version> <desc>
public static boolean verify(String publicKey, String content, String sign) {
ECPublicKeyParameters ecPublicKeyParameters;
//这里需要根据公钥的长度进行加工
if (publicKey.length() == PUBLIC_LENGTH) {
//这里需要去掉开始第一个字节 第一个字节表示标记
publicKey = publicKey.substring(2);
String xhex = publicKey.substring(0, 64);
String yhex = publicKey.substring(64, 128);
ecPublicKeyParameters = BCUtil.toSm2Params(xhex, yhex);
} else {
PublicKey p = BCUtil.decodeECPoint(publicKey, SmUtil.SM2_CURVE_NAME);
ecPublicKeyParameters = BCUtil.toParams(p);
//创建sm2 对象
SM2 sm2 = new SM2(null, ecPublicKeyParameters);
return sm2.verifyHex(HexUtil.encodeHexStr(content), sign);