召冠的博客

做对的事,脚踏实地,保持正直。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

国密SM2算法,加密、签名示例

Posted on 2025-09-10 20:37  江城2211  阅读(36)  评论(0)    收藏  举报

Java代码SM2算法加解密、签名验签的实现Demo:

package com.example.demo;


import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.*;
import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.security.Security;


public final class SM2Demo {


    static {
        Security.addProvider(new BouncyCastleProvider());
    }


    /* ---------- 密钥对 ---------- */
    public static AsymmetricCipherKeyPair genKeyPair() {
        X9ECParameters sm2 = GMNamedCurves.getByName("sm2p256v1");
        ECDomainParameters domain = new ECDomainParameters(sm2.getCurve(), sm2.getG(), sm2.getN());
        ECKeyPairGenerator gen = new ECKeyPairGenerator();
        gen.init(new ECKeyGenerationParameters(domain, new SecureRandom()));
        return gen.generateKeyPair();
    }


    /* ---------- 加密 ---------- */
    public static String encrypt(String hexPubKey, String plain) throws Exception {
        X9ECParameters sm2 = GMNamedCurves.getByName("sm2p256v1");
        ECDomainParameters domain = new ECDomainParameters(sm2.getCurve(), sm2.getG(), sm2.getN());
        ECPoint pubPoint = sm2.getCurve().decodePoint(Hex.decode(hexPubKey));
        ECPublicKeyParameters pubKey = new ECPublicKeyParameters(pubPoint, domain);


        SM2Engine engine = new SM2Engine();
        engine.init(true, new ParametersWithRandom(pubKey, new SecureRandom()));
        byte[] cipher = engine.processBlock(plain.getBytes(), 0, plain.getBytes().length);
        return Hex.toHexString(cipher);
    }


    /* ---------- 解密 ---------- */
    public static String decrypt(String hexPriKey, String hexCipher) throws Exception {
        X9ECParameters sm2 = GMNamedCurves.getByName("sm2p256v1");
        ECDomainParameters domain = new ECDomainParameters(sm2.getCurve(), sm2.getG(), sm2.getN());
        BigInteger d = new BigInteger(hexPriKey, 16);
        ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(d, domain);


        SM2Engine engine = new SM2Engine();
        engine.init(false, priKey);
        byte[] plain = engine.processBlock(Hex.decode(hexCipher), 0, Hex.decode(hexCipher).length);
        return new String(plain);
    }


    /* ---------- 签名 ---------- */
    public static String sign(String hexPriKey, String id, String plain) throws Exception {
        X9ECParameters sm2 = GMNamedCurves.getByName("sm2p256v1");
        ECDomainParameters domain = new ECDomainParameters(sm2.getCurve(), sm2.getG(), sm2.getN());
        BigInteger d = new BigInteger(hexPriKey, 16);
        ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(d, domain);


        SM2Signer signer = new SM2Signer();
        CipherParameters param = new ParametersWithID(priKey, id.getBytes());
        signer.init(true, param);
        signer.update(plain.getBytes(), 0, plain.getBytes().length);
        byte[] sig = signer.generateSignature();
        return Hex.toHexString(sig);
    }


    /* ---------- 验签 ---------- */
    public static boolean verify(String hexPubKey, String id, String plain, String hexSig) throws Exception {
        X9ECParameters sm2 = GMNamedCurves.getByName("sm2p256v1");
        ECDomainParameters domain = new ECDomainParameters(sm2.getCurve(), sm2.getG(), sm2.getN());
        ECPoint pubPoint = sm2.getCurve().decodePoint(Hex.decode(hexPubKey));
        ECPublicKeyParameters pubKey = new ECPublicKeyParameters(pubPoint, domain);


        SM2Signer signer = new SM2Signer();
        CipherParameters param = new ParametersWithID(pubKey, id.getBytes());
        signer.init(false, param);
        signer.update(plain.getBytes(), 0, plain.getBytes().length);
        return signer.verifySignature(Hex.decode(hexSig));
    }


    /* ---------- 演示 ---------- */
    public static void main(String[] args) throws Exception {
        AsymmetricCipherKeyPair kp = genKeyPair();
        String pubHex = Hex.toHexString(((ECPublicKeyParameters) kp.getPublic()).getQ().getEncoded(false));
        String priHex = ((ECPrivateKeyParameters) kp.getPrivate()).getD().toString(16);


        System.out.println("公钥: " + pubHex);
        System.out.println("私钥: " + priHex);


        String plain = "hello 国密 SM2";
        System.out.println("原始数:" + plain);
        String cipher = encrypt(pubHex, plain);
        System.out.println("加密后: " + cipher);


        String recovered = decrypt(priHex, cipher);
        System.out.println("解密后: " + recovered);


        String id = "1234567812345678";          // 国密标准推荐 16 字节 ID
        String sig = sign(priHex, id, plain);
        System.out.println("签名  : " + sig);
        boolean ok = verify(pubHex, id, plain, sig);
        System.out.println("验签结果: " + ok);
    }
}

 

pom依赖引入 :

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.70</version> <!-- 版本号可根据需要更新,1.70及以上版本对SM2支持完善 -->
</dependency>

 

参考文章:https://cloud.tencent.com/developer/article/2499894