JAVA实现国密算法SM2/SM3/SM4签名与验签(基于 BouncyCastle)

密码学算法分类指南[
国密算法全解析
Java实现国密算法 SM2 /SM3 /SM4加解密(基于 BouncyCastle)

  1. 环境要求:
  • JDK 17
  • Maven 3
  • BouncyCastle(1.78 )

先上个结论, SM2 是三种算法中唯一真正适用于数字签名的算法

一、加解密与签名验签的区别

贴代码之前,先说一下加解密与签名验签的区别:

  • 加解密:用于保密通信,使用公钥加密,私钥解密
  • 签名验签:用于身份验证和数据完整性校验, 强调真实性、完整性以及不可否认性。使用私钥签名,公钥验签

举个栗子:

1. 加解密示例

A 要给 B 寄一份重要的文件快递,但怕被别人偷看,便使用了一个只能用 B 钥匙打开的快递箱。 如图:

  1. B 提前公开了开箱钥匙(公钥);
  2. A 把文件放进快递箱里,并用这把钥匙锁住(公钥加密);
  3. A 寄出这个快递箱(密文);
  4. B 收到后,用私钥打开;
  5. 只有 B 能看到内容,别人即使拦截也无法打开。

2. 签名验签示例

A 寄文件快递时,在包裹外贴上了专属的封条(签名)。B 收到包裹后,使用 A 的公开印章验签,判断这个包括是否是 A 寄出的,内容是否被修改过。

  1. A 写好信件后,用自己专属的签名封条(私钥)封住包裹;
  2. B 接收包裹, 从公开平台获取A 的印章样式(公钥);
  3. B 比对签名是否一致;
  4. 如果验证通过,B 可以确定包裹是 A 发出的,内容也没被改过。

二、 Maven 依赖配置

pom.xml 中添加如下依赖:

<!-- 1.78 -->
<dependency>
  <groupId>org.bouncycastle</groupId>
  <artifactId>bcprov-jdk18on</artifactId>
  <version>1.78</version>
</dependency>

三. 签名工具类

工具类说明:

  • 工具类基于 Bouncy Castle 实现;
  • SM2 用于非对称签名验签;
  • SM3 用于哈希校验(非数字签名);
  • SM4 用于对称加密,可用于实现“加密认证”。

Bouncy Castle 中,SM4Engine 默认使用 ECB 模式 。类 SmBaseUtilsSmKeyGenUtils 和密钥对生成在上一篇文章中,这里就不贴了。

代码如下:

import org.bouncycastle.crypto.digests.SM3Digest;

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Base64;

/***
 * 国密算法签名工具类.
 *
 * @author shijiangyong
 * @date 2025/11/5 10:23
 **/
public class SmAlgorithmSignUtils extends SmBaseUtils{
   
   

    /**
     * SM2 签名(非对称,基于公钥/私钥).
     *
     * @param privateKey key
     * @param valueToDigest 数据
     * @return 结果
     */
    public static String sm2Sign(final String privateKey, final String valueToDigest) {
   
   
        try {
   
   
            byte[] privateKeyBytes = Base64.getDecoder().decode(privateKey);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");
            PrivateKey key = keyFactory.generatePrivate(keySpec);

            Signature signature = Signature.getInstance("SM3withSM2", "BC");
            signature.initSign(key);
            signature.update(valueToDigest.getBytes(StandardCharsets.UTF_8));
            byte[] signed = signature.sign();
            return Base64.getEncoder().encodeToString(signed);
        } catch (Exception e) {
   
   
            throw new RuntimeException("SM2 sign error", e);
        }
    }

    /**
     * SM2 验签.
     *
     * @param publicKey publicKey
     * @param value 验签数据
     * @param signatureStr 签名值
     * @return 结果
     */
    public static boolean sm2Verify(final String publicKey, final String value, final String signatureStr) {
   
   
        try {
   
   
            byte[] publicKeyBytes = Base64.getDecoder().decode(publicKey);
            X509EncodedKeySpec keySpec 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值