SM2——适用于前后端(java+vue)公用的SM2国密加解密传输

目录

    • 一、SM2国密加解密算法
      • 1.1、pom文件引入依赖包
      • 1.2、SM2加解密工具类
      • 1.3、测试类

一、SM2国密加解密算法

1.1、pom文件引入依赖包

 
     org.bouncycastle
     bcprov-jdk18on
     1.72
 

1.2、SM2加解密工具类

  • SM2加解密工具类

    package com.xz.utils;
    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 java.math.BigInteger;
    import java.security.*;
    import java.security.spec.ECGenParameterSpec;
    import java.util.HashMap;
    import java.util.Map;
    
    
    /**
     * 适用于前后端公用的SM2秘钥生成、加解密工具类
     */
    public class SimpSM2Util {
        /**
         * 公钥常量
         */
        public static final String KEY_PUBLIC_KEY = "publicKey";
        /**
         * 私钥返回值常量
         */
        public static final String KEY_PRIVATE_KEY = "privateKey";
    
        /**
         * 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;
        }
     
        /**
         * 生成密钥
         */
        public static Map createKey() throws Exception{
            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()));
            Map result = new HashMap();
            result.put(KEY_PUBLIC_KEY, Hex.toHexString(p.getQ().getEncoded(false)));
            result.put(KEY_PRIVATE_KEY, Hex.toHexString(s.getD().toByteArray()));
            return result;
        }
    
    }
    

1.3、测试类

  • 测试类

    public static void main(String[] args) throws Exception {
          Map key = createKey();
           String publicKey = key.get(KEY_PUBLIC_KEY);
           System.out.println("公钥:"+publicKey);
           String privateKey = key.get(KEY_PRIVATE_KEY);
           System.out.println("私钥:"+privateKey);
    
           String str="hello java123456";
           System.out.println("加密前结果:"+str);
           String encrypt = encrypt(publicKey, str);
           System.out.println("加密后结果:"+encrypt);
           String decrypt = decrypt(privateKey, encrypt);
           System.out.println("解密后结果:"+decrypt);
    }
    
  • 测试结果,如下图所示:

    在这里插入图片描述

本文来自网络,不代表协通编程立场,如若转载,请注明出处:https://net2asp.com/ef2499478c.html