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

前后端的SM2国密加密解密

首先给大家推荐一个款很不错的微信小程序,可以逗逗身边朋友,或者你有时候想脱身的时候,想找个理由接口 那么这个绝对是神器

1.vue 前端

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

ruby 复制代码
//导入依赖
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.导入依赖

ruby 复制代码
         <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层接口

ruby 复制代码
 
   @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);
    }
ruby 复制代码
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);
    }
 
}

工具类

ruby 复制代码
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()));
    }
}
相关推荐
uzong14 分钟前
技术故障复盘模版
后端
GetcharZp42 分钟前
基于 Dify + 通义千问的多模态大模型 搭建发票识别 Agent
后端·llm·agent
加班是不可能的,除非双倍日工资1 小时前
css预编译器实现星空背景图
前端·css·vue3
桦说编程1 小时前
Java 中如何创建不可变类型
java·后端·函数式编程
IT毕设实战小研1 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
wyiyiyi2 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
gnip2 小时前
vite和webpack打包结构控制
前端·javascript
excel2 小时前
在二维 Canvas 中模拟三角形绕 X、Y 轴旋转
前端
阿华的代码王国3 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
一条上岸小咸鱼3 小时前
Kotlin 基本数据类型(三):Booleans、Characters
android·前端·kotlin