JAVA integrado nacional secreto SM2

Una descripción general del algoritmo secreto nacional: https://blog.csdn.net/qq_38254635/article/details/131801527

SM2 Elliptic Curve Public Key Cryptography Algorithm
es un cifrado asimétrico basado en ECC. El algoritmo está disponible públicamente. Dado que el algoritmo se basa en ECC, su velocidad de firma y la velocidad de generación de claves secretas son más rápidas que RSA. ECC de 256 bits (SM2 es un tipo de ECC de 256 bits) tiene mayor seguridad que RSA de 2048 bits, pero la velocidad de operación es más rápida que RSA.

1. configuración pom

<!-- 国密 -->
<dependency>
	<groupId>org.bouncycastle</groupId>
	<artifactId>bcprov-jdk15to18</artifactId>
	<version>1.66</version>
</dependency>

2. Integración de código

2.1 Estructura del directorio

inserte la descripción de la imagen aquí

2.2 Código fuente

ConstanteClave.java

package com.secret.sm2;

public class KeyConstant {
    
    

    public static final String PRIVATE_KEY = "pveky"; // 私钥
    public static final String PUBLIC_KEY = "pbcky"; // 公钥

    public static final String GM_NAME_CURVE = "sm2p256v1";
    public static final String ALGORITHM = "SHA1PRNG";

}

ModoTipoConstante.java

package com.secret.sm2;

import org.bouncycastle.crypto.engines.SM2Engine;

public class ModeTypeConstant {
    
    

    public static final String BASE = "base";
    public static final String BC = "bc";

    @Deprecated
    public static final SM2Engine.Mode BASE_MODE = SM2Engine.Mode.C1C3C2;
    @Deprecated
    public static final SM2Engine.Mode BC_MODE = SM2Engine.Mode.C1C2C3;

    public static ModeTypeEnum getMode(String modeType){
    
    
        if (ModeTypeEnum.BASE_MODE.getType().equals(modeType)) return ModeTypeEnum.BASE_MODE;
        return ModeTypeEnum.BC_MODE;
    }

}

ModeTypeEnum.java

package com.secret.sm2;

import org.bouncycastle.crypto.engines.SM2Engine;

public enum ModeTypeEnum {
    
    

    BASE_MODE(ModeTypeConstant.BASE, SM2Engine.Mode.C1C3C2),
    BC_MODE(ModeTypeConstant.BC, SM2Engine.Mode.C1C2C3);

    private String type;
    private SM2Engine.Mode mode;

    ModeTypeEnum(String type, SM2Engine.Mode mode) {
    
    
        this.type = type;
        this.mode = mode;
    }

    public String getType(){
    
    
        return type;
    }

    public SM2Engine.Mode getMode(){
    
    
        return mode;
    }

}

SecretCommon.java

package com.secret.sm2;

import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.bouncycastle.util.encoders.Hex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;

/**
 * SM2公钥密码算法(非对称算法)
 * SM2椭圆曲线公钥密码算法是我国自主设计的公钥密码算法。
 * 包括SM2-1椭圆曲线数字签名算法;SM2-2椭圆曲线密钥交换协议;SM2-3椭圆曲线公钥加密算法,分别用于实现数字签名密钥协商和数据加密等功能。
 * SM2算法与RSA算法不同的是,SM2算法是基于椭圆曲线上点群离散对数难题,相对于RSA算法,256位的SM2密码强度已经比2048位的RSA密码强度要高。
 */
public class SecretCommon {
    
    

    //获取椭圆曲线
    public static synchronized ECDomainParameters getECDomainParameters() {
    
    
        X9ECParameters sm2ECParameters = GMNamedCurves.getByName(KeyConstant.GM_NAME_CURVE);
        return new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());
    }

    /**
     * get key pair
     */
    public static Map<String, String> createKeyPair() throws NoSuchAlgorithmException {
    
    
        ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
        keyPairGenerator.init(new ECKeyGenerationParameters(getECDomainParameters(), SecureRandom.getInstance(KeyConstant.ALGORITHM)));
        AsymmetricCipherKeyPair asymmetricCipherKeyPair = keyPairGenerator.generateKeyPair();
        Map<String, String> map = new HashMap<>();
        BigInteger bigInteger = ((ECPrivateKeyParameters) asymmetricCipherKeyPair.getPrivate()).getD();
        map.put(KeyConstant.PRIVATE_KEY, ByteUtils.toHexString(bigInteger.toByteArray()));
        // 把公钥放入map中,默认压缩公钥
        // 公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥,04的时候,可以去掉前面的04
        ECPoint ecPoint = ((ECPublicKeyParameters) asymmetricCipherKeyPair.getPublic()).getQ();
        map.put(KeyConstant.PUBLIC_KEY, ByteUtils.toHexString(ecPoint.getEncoded(false)));
        return map;
    }

    /**
     * 加密
     * @param plainText 需加密的明文字符串
     * @param publicKey 公钥
     * @param modeType base:标准;bc:BC模式
     */
    public static String encrypt(String plainText, String publicKey, ModeTypeEnum modeType) throws IOException, InvalidCipherTextException {
    
    
        return encrypt(plainText.getBytes(), publicKey, modeType.getMode());
    }

    /**
     * 加密
     * @param plainByte 需加密的明文字节数组
     * @param publicKey 公钥
     * @param mode 加密模式 ModeTypeEnum
     */
    public static String encrypt(byte[] plainByte, String publicKey, SM2Engine.Mode mode) throws IOException, InvalidCipherTextException {
    
    
        ECDomainParameters domainParameters = getECDomainParameters();
        //提取公钥点
        ECPoint ecPoint = domainParameters.getCurve().decodePoint(ByteUtils.fromHexString(publicKey));
        // 公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥, 04的时候,可以去掉前面的04
        ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(ecPoint, domainParameters);
        SM2Engine sm2Engine = new SM2Engine(mode);
        sm2Engine.init(true, new ParametersWithRandom(publicKeyParameters, new SecureRandom()));
        return ByteUtils.toHexString(sm2Engine.processBlock(plainByte, 0, plainByte.length));
    }

    /**
     * 解密
     * @param cipherText 需加密的字符串
     * @param privateKey 私钥
     * @param modeType base:标准;bc:BC模式
     */
    public static String decrypt(String cipherText, String privateKey, ModeTypeEnum modeType) throws InvalidCipherTextException, UnsupportedEncodingException {
    
    
        return decrypt(Hex.decode(cipherText), privateKey, modeType.getMode());
    }

    /**
     * 解密
     * @param cipherDataByte 密文字节数组
     * @param privateKeyHex 私钥
     * @param mode 解密模式 ModeTypeEnum
     */
    public static String decrypt(byte[] cipherDataByte, String privateKeyHex, SM2Engine.Mode mode) throws InvalidCipherTextException, UnsupportedEncodingException {
    
    
        BigInteger bigInteger = new BigInteger(privateKeyHex, 16);
        ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(bigInteger, getECDomainParameters());
        SM2Engine sm2Engine = new SM2Engine(mode);
        sm2Engine.init(false, privateKeyParameters);
        return new String(sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length), "utf-8");
    }

}

Utils.java

package com.secret.sm2;

import org.bouncycastle.crypto.InvalidCipherTextException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.Map;

public class Utils {
    
    

    /**
     * get key pair
     */
    public static Map<String, String> createKeyPair() throws NoSuchAlgorithmException {
    
    
        return SecretCommon.createKeyPair();
    }

    /**
     * encrypt
     * @param plainText 需加密的明文字符串
     * @param publicKey 公钥
     */
    public static String encrypt(String plainText, String publicKey) throws IOException, InvalidCipherTextException {
    
    
        return encrypt(plainText, publicKey, ModeTypeConstant.BASE);
    }

    /**
     * encrypt
     * @param plainText 需加密的明文字符串
     * @param publicKey 公钥
     * @param modeType base:标准;bc:BC模式
     */
    public static String encrypt(String plainText, String publicKey, String modeType) throws IOException, InvalidCipherTextException {
    
    
        return SecretCommon.encrypt(plainText, publicKey, ModeTypeConstant.getMode(modeType));
    }

    /**
     * decrypt
     * @param cipherText 需加密的字符串
     * @param privateKey 私钥
     */
    public static String decrypt(String cipherText, String privateKey) throws InvalidCipherTextException, UnsupportedEncodingException {
    
    
        return decrypt(cipherText, privateKey, ModeTypeConstant.BASE);
    }

    /**
     * decrypt
     * @param cipherText 需加密的字符串
     * @param privateKey 私钥
     * @param modeType base:标准;bc:BC模式
     */
    public static String decrypt(String cipherText, String privateKey, String modeType) throws InvalidCipherTextException, UnsupportedEncodingException {
    
    
        return SecretCommon.decrypt(cipherText, privateKey, ModeTypeConstant.getMode(modeType));
    }

}

Clase de prueba: Test.java

package com.secret.sm2;

import java.util.Map;

public class Test {
    
    

    public static void main(String[] args) throws Exception {
    
    
        Map<String, String> createKeyPair = Utils.createKeyPair();
        System.out.println("秘钥对:" + createKeyPair);
        String privateKey = createKeyPair.get(KeyConstant.PRIVATE_KEY);
        String publicKey = createKeyPair.get(KeyConstant.PUBLIC_KEY);
        String text = "I believe you can do anything";
        String encrypt = Utils.encrypt(text, publicKey);
        System.out.println("加密后密文:" + encrypt);
        String decrypt = Utils.decrypt(encrypt, privateKey);
        System.out.println("解密后明文:" + decrypt);
    }

}

2.3 Prueba

Los resultados de la prueba se muestran en la figura:
inserte la descripción de la imagen aquí
consulte la clase de prueba para el método de uso.

3. Enlaces relacionados

Una descripción general del algoritmo secreto nacional: https://blog.csdn.net/qq_38254635/article/details/131801527

Secreto nacional integrado JAVA SM3: https://blog.csdn.net/qq_38254635/article/details/131810696

Secreto nacional integrado JAVA SM4: https://blog.csdn.net/qq_38254635/article/details/131810715

Supongo que te gusta

Origin blog.csdn.net/qq_38254635/article/details/131810661
Recomendado
Clasificación