SpringBoot集成国产加密SM2

本文介绍了如何在Java中使用SM2加密算法,包括生成公私钥、加密和解密操作,以及使用BouncyCastleProvider和SM2Engine两种方式实现。
摘要由CSDN通过智能技术生成

依赖:

        <!--国产加密算法-->
        <!-- SM加密算法依赖 -->
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.68</version>
        </dependency>

java代码:

package com.cj.core.utils.md5;

import com.cj.core.exception.MyException;
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;

import javax.crypto.Cipher;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.ECGenParameterSpec;
import java.util.Base64;

/**
 * @Author: LiuLei
 * @Description: SM2工具类
 * @Date: 2023/9/15  17:38
 * @Version: 1.0
 */
public class Sm2Utils {
    /**
     * 编码方式
     */
    private static final String ENCODING = "UTF-8";
    private static String PUBLIC_KEY = "公钥";
    private static String PRIVATE_KEY = "私钥";


    /**
     * SM2 生成公私钥
     *
     * @return 公私钥
     */
    public static void generateKeyPair() {
        try {
            BouncyCastleProvider provider = new BouncyCastleProvider();

            // 获取椭圆曲线相关生成参数规格
            ECGenParameterSpec genParameterSpec = new ECGenParameterSpec("sm2p256v1");
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", provider);

            // 使用SM2的算法区域初始化密钥生成器
            keyPairGenerator.initialize(genParameterSpec, new SecureRandom());

            // 生成密钥对
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            BCECPrivateKey exPrivateKey = (BCECPrivateKey) keyPair.getPrivate();
            BCECPublicKey ecPublicKey = (BCECPublicKey) keyPair.getPublic();

            // 解密密钥
            BigInteger privateKey = exPrivateKey.getD();
            // 加密密钥
            ECPoint publicKey = ecPublicKey.getQ();
            System.out.println("私钥:");
            System.out.println(privateKey.toString(16));
            System.out.println("公钥:");
            System.out.println(new String(Hex.encode(publicKey.getEncoded(true))));
        } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
            throw new MyException(e.getMessage());
        }
    }

    /**
     * 加密
     * C1C2C3
     * @param source
     * @return
     */
    public static String encrypt(String source) {
        String resultStr = null;
        BouncyCastleProvider provider = new BouncyCastleProvider();
        // 获取SM2相关参数
        X9ECParameters parameters = GMNamedCurves.getByName("sm2p256v1");
        // 椭圆曲线参数规格
        ECParameterSpec ecParameterSpec = new ECParameterSpec(parameters.getCurve(), parameters.getG(), parameters.getN(), parameters.getH());
        // 将公钥HEX字符串转换为椭圆曲线对应的点
        ECPoint ecPoint = parameters.getCurve().decodePoint(Hex.decode(PUBLIC_KEY));
        try {
            byte[] srcData = source.getBytes(ENCODING);
            // 获取椭圆曲线KEY生成器
            KeyFactory keyFactory = KeyFactory.getInstance("EC", provider);
            // 将椭圆曲线点转为公钥KEY对象
            BCECPublicKey bcecPublicKey = (BCECPublicKey) keyFactory.generatePublic(new ECPublicKeySpec(ecPoint, ecParameterSpec));
            // 获取SM2加密器
            Cipher cipher = Cipher.getInstance("SM2", provider);
            // 初始化为加密模式
            cipher.init(Cipher.ENCRYPT_MODE, bcecPublicKey);
            byte[] result = cipher.doFinal(srcData);
            // 加密并编码为base64格式
            resultStr = Base64.getEncoder().encodeToString(result);
        } catch (Exception e) {
            throw new MyException(e.getMessage());
        }
        return resultStr;
    }


    /**
     * SM2加密算法
     *
     * @param source 明文数据
     * @return
     */
    public static String encrypt2(String source) {
        // 获取一条SM2曲线参数
        X9ECParameters sm2Parameters = GMNamedCurves.getByName("sm2p256v1");
        // 构造ECC算法参数,曲线方程、椭圆曲线G点、大整数N
        ECDomainParameters domainParameters = new ECDomainParameters(sm2Parameters.getCurve(), sm2Parameters.getG(), sm2Parameters.getN());
        //提取公钥点
        ECPoint pukPoint = sm2Parameters.getCurve().decodePoint(Hex.decode(PUBLIC_KEY));
        // 公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥, 04的时候,可以去掉前面的04
        ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(pukPoint, domainParameters);
        ParametersWithRandom parametersWithRandom = new ParametersWithRandom(publicKeyParameters, new SecureRandom());
        SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C2C3);
        // 设置sm2为加密模式
        sm2Engine.init(true, parametersWithRandom);
        String resultStr = null;
        try {
            byte[] srcData = source.getBytes(ENCODING);
            byte[] result = sm2Engine.processBlock(srcData, 0, srcData.length);
            // 加密并编码为base64格式
            resultStr = Base64.getEncoder().encodeToString(result);
        } catch (Exception e) {
            throw new MyException(e.getMessage());
        }
        return resultStr;

    }

    /**
     * 解密
     * C1C2C3
     * @param source
     * @return
     */
    public static String decrypt(String source) {
        String resultStr = null;
        BouncyCastleProvider provider = new BouncyCastleProvider();
        // 获取SM2相关参数
        X9ECParameters parameters = GMNamedCurves.getByName("sm2p256v1");
        // 椭圆曲线参数规格
        ECParameterSpec ecParameterSpec = new ECParameterSpec(parameters.getCurve(), parameters.getG(), parameters.getN(), parameters.getH());
        // 将私钥HEX字符串转换为X值
        BigInteger bigInteger = new BigInteger(PRIVATE_KEY, 16);
        try {
            //内容转byte数组
            byte[] srcData = Base64.getDecoder().decode(source);
            // 获取椭圆曲线KEY生成器
            KeyFactory keyFactory = KeyFactory.getInstance("EC", provider);
            // 将X值转为私钥KEY对象
            BCECPrivateKey bcecPrivateKey = (BCECPrivateKey) keyFactory.generatePrivate(new ECPrivateKeySpec(bigInteger, ecParameterSpec));
            // 获取SM2加密器
            Cipher cipher = Cipher.getInstance("SM2", provider);
            // 初始化为加密模式
            cipher.init(Cipher.DECRYPT_MODE, bcecPrivateKey);
            byte[] result = cipher.doFinal(srcData);
            // 解密
            resultStr = new String(result, ENCODING);
        } catch (Exception e) {
            throw new MyException(e.getMessage());
        }
        return resultStr;
    }

    /**
     * SM2解密算法
     *
     * @param source 密文数据
     * @return
     */
    public static String decrypt2(String source) {
        BigInteger privateKeyD = new BigInteger(PRIVATE_KEY, 16);
        //获取一条SM2曲线参数
        X9ECParameters sm2Parameters = GMNamedCurves.getByName("sm2p256v1");
        //构造domain参数
        ECDomainParameters domainParameters = new ECDomainParameters(sm2Parameters.getCurve(), sm2Parameters.getG(), sm2Parameters.getN());
        ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(privateKeyD, domainParameters);
        SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C2C3);
        // 设置sm2为解密模式
        sm2Engine.init(false, privateKeyParameters);
        String resultStr = null;
        try {
            //内容转byte数组
            byte[] srcData = Base64.getDecoder().decode(source);
            byte[] result = sm2Engine.processBlock(srcData, 0, srcData.length);
            // 解密
            resultStr = new String(result, ENCODING);
        } catch (Exception e) {
            throw new MyException(e.getMessage());
        }
        return resultStr;
    }
}

这里用了两种实现方式:Cipher 和 SM2Engine

这两种方式加密的结果可以互相通用

Cipher:这种写法我现在还没找到切换 C1C2C3 和 C!C3C2 的方式 只能默认使用C1C2C3 

                
Spring Boot中使用JCE (Java Cryptography Extension) 和SM2进行的是非对称加密操作,特别是对于中国国密算法SM2SM2是一种安全多方密码系统,它提供了一种基于椭圆曲线的公钥加密方案。 在Spring Boot项目中,如果你需要集成SM2,通常会做以下步骤: 1. **添加依赖**:在项目的pom.xml文件中添加Spring Security或专门处理国密的库如`bcprov-jdk15on`(Bouncy Castle的一个版本,支持SM2)作为依赖。 ```xml <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.70</version> </dependency> ``` 2. **配置**:配置应用的安全管理,指定SM2算法作为默认的加密算法。 ```java @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.withProvider(new JceAuthProvider()); } // 使用BCprov provider @Bean public JcaAuthProvider jceAuthProvider() { JcaAuthProvider provider = new JcaAuthProvider(); provider.setAlgorithm("SM2"); return provider; } } ``` 3. **使用**:在需要加密解密的地方,比如JWT令牌生成、HTTP请求头等,可以使用Spring提供的`CryptoUtils`类或自定义工具类来操作SM2密钥对。 ```java import org.springframework.security.crypto.encrypt.TextEncryptor; // ... TextEncryptor encryptor = CryptoUtils.getEncryptor(jceAuthProvider(), "your-secret-key"); String encryptedValue = encryptor.encrypt("plain-text"); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值