惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Hacker News: Front Page
博客园_首页
大猫的无限游戏
大猫的无限游戏
有赞技术团队
有赞技术团队
Microsoft Azure Blog
Microsoft Azure Blog
Recorded Future
Recorded Future
博客园 - Franky
Application and Cybersecurity Blog
Application and Cybersecurity Blog
U
Unit 42
S
Secure Thoughts
博客园 - 司徒正美
美团技术团队
C
Cisco Blogs
The GitHub Blog
The GitHub Blog
G
Google Developers Blog
V
Vulnerabilities – Threatpost
T
Troy Hunt's Blog
S
Security Affairs
爱范儿
爱范儿
AWS News Blog
AWS News Blog
Help Net Security
Help Net Security
Blog — PlanetScale
Blog — PlanetScale
T
Threatpost
F
Fortinet All Blogs
Scott Helme
Scott Helme
酷 壳 – CoolShell
酷 壳 – CoolShell
B
Blog RSS Feed
O
OpenAI News
S
Schneier on Security
Stack Overflow Blog
Stack Overflow Blog
T
Tor Project blog
AI
AI
D
DataBreaches.Net
PCI Perspectives
PCI Perspectives
T
Tailwind CSS Blog
Martin Fowler
Martin Fowler
P
Palo Alto Networks Blog
C
CERT Recently Published Vulnerability Notes
腾讯CDC
T
Tenable Blog
人人都是产品经理
人人都是产品经理
Recent Announcements
Recent Announcements
C
Cyber Attacks, Cyber Crime and Cyber Security
Jina AI
Jina AI
Hacker News - Newest:
Hacker News - Newest: "LLM"
Google Online Security Blog
Google Online Security Blog
S
Securelist
P
Proofpoint News Feed
L
LINUX DO - 最新话题
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报

博客园 - 江城2211

大数值的精度与格式化显示问题 【知识总结】数据库的事务、并发与锁管理 基于数据源连接,动态构造JPA上下文EntityManager 【转载】使用了HTTPS为啥还要接口数据加密? RSA加密算法,加解密、签名示例 【知识总结】JVM线程堆栈中的基础概念解读 【问题记录】JVM进程崩溃(hs_err_pid.log致命错误日志) [问题记录】存在视图依赖的数据表,DDL修改字段比如做扩容等注意事项 【编码技巧】批量校验或处理关联引用数据的优化总结 【问题总结】Garmin路线无法同步和地图坐标偏移的解决办法 【工具推荐】磁盘IO检测工具之Diskspd 【编码技巧】总结一个稳定而高效的方法,将二维关系数据转换为树形结构 【编程技巧】SQL脚本快速生成随机测试数据 【编程技巧】结合JPA通用分页与排序技术,支持百万级以上数据的DML批量处理方案 【使用技巧】CodeDecom.exe批量反编译JAR包+Beyond Compare对比 【问题记录】Cause: java.sql.SQLRecoverableException: No more data to read from socket JDBC与各数据库产品连接的驱动及URL示例 【问题记录】使用PowerDesigner连接数据库并反向工程生成所有表及关系 使用tcpdump抓取网络包,在wareshark查看对应请求及响应的原始报文
国密SM2算法,加密、签名示例
江城2211 · 2025-09-10 · via 博客园 - 江城2211

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

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