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);