前端后端的SM2国密加密解密

时间:2024-03-29 18:28:22

前后端的SM2国密加密解密

在这里插入图片描述

首先给大家推荐一个款很不错的微信小程序,可以逗逗身边朋友,或者你有时候想脱身的时候,想找个理由接口 那么这个绝对是神器
![请添加图片描述](https://img-blog.csdnimg.cn/direct/112c23bbb53f41f187c7e29f5c81c139.jpeg

1.vue 前端
1.1导入依赖及前端代码示例

//导入依赖
npm install --save sm-crypto
 
 
//页面引入
import { sm2 } from 'sm-crypto';
 
methods: {
    handleLogin() {
      this.$refs.loginForm.validate(valid => {
      
//示例此处为传入密码加密然后得到加密后的数据this.loginForm.password
          this.loginForm.password = this.rsaPublicData(this.loginForm.password);
     
      });
    },
//加密的方法
    rsaPublicData(data) {
//publicKey 为sm2的公钥,公钥用来加密,私钥用来解密
//示例对应的私钥为 74a89d4e78dd999a1882e0202566ee8971464eaf097dede170c86ad683e6e751  用来给后端解密用
      const publicKey =
        '0476cf11ef3ab14ac836c0bf850c46cb96402c1d7dd4ded1591a4e5a4fea8951a96a842b4d4e7b9ec6fd779ccc6ef8d83ee7623184e6788847ed0c827351d41093';
 
      const cipherMode = 1;
//data为加密的数据
      const result = sm2.doEncrypt(data, publicKey, cipherMode);
      return result;
    },
 
 
}

2.后端代码示例
1.导入依赖

         <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.69</version>
        </dependency>

2.代码示例
1.controller层接口

 
   @PostMapping("/login")
    public R login(@RequestBody User user) {
//示例私钥
        String privateKey = "74a89d4e78dd999a1882e0202566ee8971464eaf097dede170c86ad683e6e751";
//示例公钥
         String publicKey = "0476cf11ef3ab14ac836c0bf850c46cb96402c1d7dd4ded1591a4e5a4fea8951a96a842b4d4e7b9ec6fd779ccc6ef8d83ee7623184e6788847ed0c827351d41093";
        System.out.println("privateKey"+privateKey);
//privateKey 为私钥  publicKey为公钥,重要的是私钥
         LoSM2.InitKey(privateKey, publicKey);
//user.getPassword()为加密后要解密的数据
        String encrypt = LoSM2.decrypt(user.getPassword());
        String s = decrypt1(user.getPassword());
        System.out.println("解码密码:+"+encrypt);
        System.out.println("解码s密码:"+s);
        return R.ok().data("密码",encrypt);
    }
import org.bouncycastle.crypto.engines.SM2Engine;
 
/**
 * 简单单例SM2加解密, 配合前端
 */
public class LoSM2 {
 
    private static String ECNameModel = "sm2p256v1";
    private static SM2Engine.Mode CipherMode = SM2Engine.Mode.C1C3C2;
    private final String privateKey;
    private final String publicKey;
 
    private LoSM2(String privateKey, String publicKey){
        this.privateKey = privateKey;
        this.publicKey = publicKey;
    }
 
    private volatile static LoSM2 instance = null;
 
    public static LoSM2 getInstance(){
        if(instance == null){
            throw new RuntimeException("请InitKey初始化密钥!!!");
        }
        return instance;
    }
 
    /**
     * SM2初始密钥(私钥,公钥)
     * @param privateKey
     * @param publicKey
     * @return
     */
    public static LoSM2 InitKey(String privateKey, String publicKey) {
        System.out.println(instance.privateKey);
        if(instance == null){
            synchronized(LoSM2.class){
                if(instance == null){
                    instance = new LoSM2(privateKey, publicKey);
                }
            }
        }
        return instance;
    }
 
    private static class SM2SimpSelfLoader {
        private static final LoSM2 instance = InitKey("", "");
    }
 
    private static boolean IsInitKey(){
        if(instance == null) {
            throw new RuntimeException("请InitKey初始化密钥!!!");
        }else {
            return true;
        }
    }
 
    /**
     * SM2加密
     * @param cleartext          明文数据
     */
    public String encrypt(String cleartext) {
        if(!IsInitKey()){
            return "";
 
        }
        return SimpSM2Util.encrypt(instance.publicKey, cleartext);
    }
 
    /**
     * SM2解密
     * @param cipherData        密文数据
     */
    public static String decrypt(String cipherData) {
        if(!IsInitKey()){
            System.out.println(instance);
            System.out.println(IsInitKey());
            return "";
        }
        return SimpSM2Util.decrypt(instance.privateKey, cipherData);
    }
 
}

工具类

import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.*;
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.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;
import org.junit.Test;
 
import java.math.BigInteger;
import java.security.*;
import java.security.spec.ECGenParameterSpec;
 
 
/**
 * 简单的sm2
 */
public class SimpSM2Util {
 
    /**
     * SM2加密算法
     * @param publicKey     公钥
     * @param data          明文数据
     * @return
     */
    public static String encrypt(String publicKey, String data) {
        // 获取一条SM2曲线参数
        X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
        // 构造ECC算法参数,曲线方程、椭圆曲线G点、大整数N
        ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());
        //提取公钥点
        ECPoint pukPoint = sm2ECParameters.getCurve().decodePoint(Hex.decode(publicKey));
        // 公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥, 04的时候,可以去掉前面的04
        ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(pukPoint, domainParameters);
 
        SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C3C2);
        // 设置sm2为加密模式
        sm2Engine.init(true, new ParametersWithRandom(publicKeyParameters, new SecureRandom()));
 
        byte[] arrayOfBytes = null;
        try {
            byte[] in = data.getBytes();
            arrayOfBytes = sm2Engine.processBlock(in, 0, in.length);
        } catch (Exception e) {
            System.out.println("SM2加密时出现异常:"+e.getMessage());
        }
        return Hex.toHexString(arrayOfBytes);
 
    }
 
    /**
     * SM2解密算法
     * @param privateKey        私钥
     * @param cipherData        密文数据
     * @return
     */
    public static String decrypt(String privateKey, String cipherData) {
        // 使用BC库加解密时密文以04开头,传入的密文前面没有04则补上
        if (!cipherData.startsWith("04")){
            cipherData = "04" + cipherData;
        }
        byte[] cipherDataByte = Hex.decode(cipherData);
        BigInteger privateKeyD = new BigInteger(privateKey, 16);
        //获取一条SM2曲线参数
        X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
        //构造domain参数
        ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());
        ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(privateKeyD, domainParameters);
 
        SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C3C2);
        // 设置sm2为解密模式
        sm2Engine.init(false, privateKeyParameters);
 
        String result = "";
        try {
            byte[] arrayOfBytes = sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length);
            return new String(arrayOfBytes);
        } catch (Exception e) {
            System.out.println("SM2解密时出现异常:"+e.getMessage());
        }
        return result;
    }
 
    @Test
     //生成密钥
    public void createKey() throws Exception{
        //String M="encryption standard111111111111111111111111111111";
        SimpSM2Util sm2 = new SimpSM2Util();
        ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");
        // 获取一个椭圆曲线类型的密钥对生成器
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());
        // 使用SM2参数初始化生成器
        kpg.initialize(sm2Spec);
        // 获取密钥对
        KeyPair keyPair = kpg.generateKeyPair();
        PublicKey publicKey = keyPair.getPublic();
        BCECPublicKey p=(BCECPublicKey)publicKey;
        System.out.println("publicKey:"+Hex.toHexString(p.getQ().getEncoded(false)));
        PrivateKey privateKey = keyPair.getPrivate();
        BCECPrivateKey s=(BCECPrivateKey)privateKey;
        System.out.println("privateKey:"+Hex.toHexString(s.getD().toByteArray()));
    }
}