国密算法概述:https://blog.csdn.net/qq_38254635/article/details/131801527
SM2椭圆曲线公钥密码算法
为非对称加密,基于ECC。该算法已公开。由于该算法基于ECC,故其签名速度与秘钥生成速度都快于RSA。ECC 256位(SM2采用的就是ECC 256位的一种)安全强度比RSA 2048位高,但运算速度快于RSA。
一、pom配置
org.bouncycastle bcprov-jdk15to18 1.66
二、代码集成
2.1、目录结构
2.2、源码
KeyConstant.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";}
ModeTypeConstant.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;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()); } public static Map createKeyPair() throws NoSuchAlgorithmException { ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator(); keyPairGenerator.init(new ECKeyGenerationParameters(getECDomainParameters(), SecureRandom.getInstance(KeyConstant.ALGORITHM))); AsymmetricCipherKeyPair asymmetricCipherKeyPair = keyPairGenerator.generateKeyPair(); Map 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; } public static String encrypt(String plainText, String publicKey, ModeTypeEnum modeType) throws IOException, InvalidCipherTextException { return encrypt(plainText.getBytes(), publicKey, modeType.getMode()); } 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)); } public static String decrypt(String cipherText, String privateKey, ModeTypeEnum modeType) throws InvalidCipherTextException, UnsupportedEncodingException { return decrypt(Hex.decode(cipherText), privateKey, modeType.getMode()); } 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 { public static Map createKeyPair() throws NoSuchAlgorithmException { return SecretCommon.createKeyPair(); } public static String encrypt(String plainText, String publicKey) throws IOException, InvalidCipherTextException { return encrypt(plainText, publicKey, ModeTypeConstant.BASE); } public static String encrypt(String plainText, String publicKey, String modeType) throws IOException, InvalidCipherTextException { return SecretCommon.encrypt(plainText, publicKey, ModeTypeConstant.getMode(modeType)); } public static String decrypt(String cipherText, String privateKey) throws InvalidCipherTextException, UnsupportedEncodingException { return decrypt(cipherText, privateKey, ModeTypeConstant.BASE); } public static String decrypt(String cipherText, String privateKey, String modeType) throws InvalidCipherTextException, UnsupportedEncodingException { return SecretCommon.decrypt(cipherText, privateKey, ModeTypeConstant.getMode(modeType)); }}
测试类:Test.java
package com.secret.sm2;import java.util.Map;public class Test { public static void main(String[] args) throws Exception { Map 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、测试
测试结果如图:
使用方法参考测试类即可。
三、相关链接
国密算法概述:https://blog.csdn.net/qq_38254635/article/details/131801527
JAVA集成国密SM3:https://blog.csdn.net/qq_38254635/article/details/131810696
JAVA集成国密SM4:https://blog.csdn.net/qq_38254635/article/details/131810715
来源地址:https://blog.csdn.net/qq_38254635/article/details/131810661