国密SM2加解密Demo

国密SM2加解密Demo

1、pom.xml

<!-- 国密 START-->
<!--        <dependency>-->
<!--            <groupId>org.bouncycastle</groupId>-->
<!--            <artifactId>bcprov-jdk15to18</artifactId>-->
<!--            <version>1.71</version>-->
<!--        </dependency>-->
<!-- 国密 END -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.5.8</version>
</dependency>

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

 

posted @ 2023-02-27 09:55  整合侠  阅读(970)  评论(0编辑  收藏  举报