sm2加密
参考:https://www.cnblogs.com/wangjintao-0623/p/10457596.html
一、概念
SM2是国家密码管理局于2010年12月17日发布的椭圆曲线公钥密码算法。
二、依赖
依赖
<dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.56</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-ext-jdk15to18</artifactId>
            <version>1.68</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15to18</artifactId>
            <version>1.68</version>
        </dependency>
三、应用
1、处理公钥
//  对获取的公钥增加一个处理,判断获取的公钥是否是16进制或者是否是base64,如果是base64,需要先转16进制,再传值使用
if (GlobleVariable.publicKey != null && Util.isBase64(GlobleVariable.publicKey)) { 
                    Base64.Decoder decoder = Base64.getDecoder();
                    byte[] bytes = decoder.decode(GlobleVariable.publicKey.getBytes(StandardCharsets.UTF_8));
                    GlobleVariable.publicKey = new String(bytes);
                    log.info("BASE64解密:" + new String(bytes));
                }
                log.info("publicKey:" + GlobleVariable.publicKey);
2、sm2加密
 passwordSM2 = SM2Utils.encrypt(Util.hexStringToBytes(GlobleVariable.publicKey), password.getBytes(StandardCharsets.UTF_8));
            log.info("SM2加密后密码:" + passwordSM2);
3、工具类
package com.bestway.imine.ai.util;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URLEncoder;
import cn.hutool.crypto.BCUtil;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECPoint;
 
public class SM2Utils {
    //生成随机秘钥对
    public static SM2KeyPair generateKeyPair() {
        SM2 sm2 = SM2.Instance();
        AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.generateKeyPair();
        ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();
        ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();
        BigInteger privateKey = ecpriv.getD();
        ECPoint publicKey = ecpub.getQ();
        System.out.println("公钥: " + Util.byteToHex(publicKey.getEncoded()));
        System.out.println("私钥: " + Util.byteToHex(privateKey.toByteArray()));
        return new SM2KeyPair(Util.byteToHex(publicKey.getEncoded(false)), Util.byteToHex(privateKey.toByteArray()));
    }
 
 
    //数据加密
    public static String encrypt(byte[] publicKey, byte[] data) throws IOException {
        if (publicKey == null || publicKey.length == 0) {
            return null;
        }
 
        if (data == null || data.length == 0) {
            return null;
        }
 
        byte[] source = new byte[data.length];
        System.arraycopy(data, 0, source, 0, data.length);
 
        Cipher cipher = new Cipher();
        SM2 sm2 = SM2.Instance();
        ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey);
 
        ECPoint c1 = cipher.Init_enc(sm2, userKey);
        cipher.Encrypt(source);
        byte[] c3 = new byte[32];
        cipher.Dofinal(c3);
 
//      System.out.println("C1 " + Util.byteToHex(c1.getEncoded()));
//      System.out.println("C2 " + Util.byteToHex(source));
//      System.out.println("C3 " + Util.byteToHex(c3));
        //C1 C2 C3拼装成加密字串
        return Util.byteToHex(c1.getEncoded(false)) + Util.byteToHex(source) + Util.byteToHex(c3);
 
    }
 
    //数据解密
    public static byte[] decrypt(byte[] privateKey, byte[] encryptedData) throws IOException {
        if (privateKey == null || privateKey.length == 0) {
            return null;
        }
 
        if (encryptedData == null || encryptedData.length == 0) {
            return null;
        }
        //加密字节数组转换为十六进制的字符串 长度变为encryptedData.length * 2
        String data = Util.byteToHex(encryptedData);
        /***分解加密字串
         * (C1 = C1标志位2位 + C1实体部分128位 = 130)
         * (C3 = C3实体部分64位  = 64)
         * (C2 = encryptedData.length * 2 - C1长度  - C2长度)
         */
        byte[] c1Bytes = Util.hexToByte(data.substring(0, 130));
        int c2Len = encryptedData.length - 97;
        byte[] c2 = Util.hexToByte(data.substring(130, 130 + 2 * c2Len));
        byte[] c3 = Util.hexToByte(data.substring(130 + 2 * c2Len, 194 + 2 * c2Len));
 
        SM2 sm2 = SM2.Instance();
        BigInteger userD = new BigInteger(1, privateKey);
 
        //通过C1实体字节来生成ECPoint
        ECPoint c1 = sm2.ecc_curve.decodePoint(c1Bytes);
        Cipher cipher = new Cipher();
        cipher.Init_dec(userD, c1);
        cipher.Decrypt(c2);
        cipher.Dofinal(c3);
 
        //返回解密结果
        return c2;
    }
    public static void test(String[] args) throws Exception {
        //生成密钥对
        generateKeyPair();
        String plainText = "lxw测试!@#¥%……&*()";
        //下面的秘钥可以使用generateKeyPair()生成的秘钥内容
        // 国密规范正式私钥
        String prik = "7BF3DC32F3CCA2176CD8EA9267EE06E02E51378E7EA52CCEB42346BE70186804";
        // 国密规范正式公钥
        String pubk = "0497077E61FA0168D4EB00F475CAA21629D8BE5377311EAB2BB59D98B00970D0B9571935D8D4DB4DB8C24923FEBC3951088805EBF7989F16694CE57A903D24317B";
        System.out.println("-------加密: ");
        String cipherText = SM2Utils.encrypt(Util.hexStringToBytes(pubk), plainText.getBytes());
        System.out.println(cipherText);
        System.out.println("-------加密后字符串长度:" + cipherText.length());
        System.out.println("-------解密: ");
        byte[] decrypt = SM2Utils.decrypt(Util.hexStringToBytes(prik), Util.hexStringToBytes(cipherText));
        System.out.println(new String(decrypt));
    }
 
 
//    public static void main(String[] args) throws Exception {
//        //生成密钥对
//        //generateKeyPair();
//        String plainText = "123456";
//        //下面的秘钥可以使用generateKeyPair()生成的秘钥内容
//        // 国密规范正式私钥
//        //String prik = "00BC0A360414F857903EB3361F2E611A11A288251171D9E7EE26E572FF51E42F3D";
//        // 国密规范正式公钥
//        String pubk = "0468DE44F089427DCC9325C0507AC768E8B1EA1DF38B6554E0AE2F50BBA82F4F39CC2A83752E4177C65F4A3EABA6FF1522F9330BB34702E4C3373939E340DAB492";
//
//        //String pubk = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCmRNl1TzcZKe8jFJnPt7wPOo/hVf0yIiqPYvusIMnIw+wqGs+cnR/1ddE2jncDAES1FMWx0QPg9v4lvi/DeBgnPwk1W75sJ4kGHB3FwbfdA6o44tMj7octz+AnYwn3yFjxwI2KdyoVg2j8Bf81SLmirR9K6Eio7f+5bms/4AdbQIDAQAB";
//        //String test2 = Util.getHexString(pubk.getBytes(), true);
//        System.out.println("-------test2: " + pubk);
//        System.out.println("-------加密后字符串: ");
//        String cipherText = SM2Utils.encrypt(Util.hexStringToBytes(pubk), plainText.getBytes());
//        System.out.println(cipherText);
//        System.out.println("-------加密后字符串长度:" + cipherText.length());
//        System.out.println("-------明文: ");
//        //byte[] decrypt = SM2Utils.decrypt(Util.hexStringToBytes(prik), Util.hexStringToBytes(cipherText));
//       //System.out.println(new String(decrypt));
//
//        String urlString = URLEncoder.encode(cipherText, "utf-8");  //输出%E4%BD%A0%E5%A5%BD
//        System.out.println(urlString);
//
//
//
//    }
 
}
4、辅助类
package com.bestway.imine.ai.util;
import java.math.BigInteger;
import java.security.SecureRandom;
 
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.ec.ECFieldElement.Fp;
 
public class SM2 {
 
    //正式参数
    public static String[] ecc_param = {
            "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",
            "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",
            "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",
            "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",
            "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",
            "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"
    };
 
    public static SM2 Instance() {
        return new SM2();
    }
 
    public final BigInteger ecc_p;
    public final BigInteger ecc_a;
    public final BigInteger ecc_b;
    public final BigInteger ecc_n;
    public final BigInteger ecc_gx;
    public final BigInteger ecc_gy;
    public final ECCurve ecc_curve;
    public final ECPoint ecc_point_g;
    public final ECDomainParameters ecc_bc_spec;
    public final ECKeyPairGenerator ecc_key_pair_generator;
    public final ECFieldElement ecc_gx_fieldelement;
    public final ECFieldElement ecc_gy_fieldelement;
 
    public SM2() {
        this.ecc_p = new BigInteger(ecc_param[0], 16);
        this.ecc_a = new BigInteger(ecc_param[1], 16);
        this.ecc_b = new BigInteger(ecc_param[2], 16);
        this.ecc_n = new BigInteger(ecc_param[3], 16);
        this.ecc_gx = new BigInteger(ecc_param[4], 16);
        this.ecc_gy = new BigInteger(ecc_param[5], 16);
 
        this.ecc_gx_fieldelement = new Fp(this.ecc_p, this.ecc_gx);
        this.ecc_gy_fieldelement = new Fp(this.ecc_p, this.ecc_gy);
 
        this.ecc_curve = new ECCurve.Fp(this.ecc_p, this.ecc_a, this.ecc_b);
        this.ecc_point_g = new ECPoint.Fp(this.ecc_curve, this.ecc_gx_fieldelement, this.ecc_gy_fieldelement);
 
        this.ecc_bc_spec = new ECDomainParameters(this.ecc_curve, this.ecc_point_g, this.ecc_n);
 
        ECKeyGenerationParameters ecc_ecgenparam;
        ecc_ecgenparam = new ECKeyGenerationParameters(this.ecc_bc_spec, new SecureRandom());
 
        this.ecc_key_pair_generator = new ECKeyPairGenerator();
        this.ecc_key_pair_generator.init(ecc_ecgenparam);
    }
}
package com.bestway.imine.ai.util;
public class SM2KeyPair {
 
    /** 公钥 */
    private  String publicKey;
 
    /** 私钥 */
    private String privateKey;
 
    SM2KeyPair(String publicKey, String privateKey) {
        this.publicKey = publicKey;
        this.privateKey = privateKey;
    }
 
    public String getPublicKey() {
        return publicKey;
    }
 
    public String getPrivateKey() {
        return privateKey;
    }
 
}
 
                    
                
 
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号