返回顶部
首页 > 资讯 > 后端开发 > JAVA >国密SM2: 加解密实现 java代码完整示例
  • 837
分享到

国密SM2: 加解密实现 java代码完整示例

java算法 2023-08-31 05:08:46 837人浏览 泡泡鱼
摘要

目录  具体Java代码SM2算法加解密实现Demo: pom依赖引入 :  国家密码管理局于2010年12月17日发布了SM2算法,并要求现有的基于RSA算法的电子认证系统、密钥管理系统、应用系统进升级改造,使用支持国密SM2算法的证

目录

 具体Java代码SM2算法加解密实现Demo:

pom依赖引入 : 

国家密码管理局于2010年12月17日发布了SM2算法,并要求现有的基于RSA算法的电子认证系统、密钥管理系统、应用系统进升级改造,使用支持国密SM2算法的证书。

  

基于ECC椭圆曲线算法的SM2算法,则普遍采用256位密钥长度,它的单位安全强度相对较高,在工程应用中比较难以实现,破译或求解难度基本上是指数级的。因此,SM2算法可以用较少的计算能力提供比RSA算法更高的安全强度,而所需的密钥长度却远比RSA算法低。 

对比项目ECC加密算法RSA加密算法
密钥长度256位2048位
CPU占用较少较高
内存占用较少较高
网络消耗较低较高
加密效率较高一般
破解难度具有数据特性,破解难度大相对ECC理论上容易些
抗攻击性一般
可扩展性一般
兼容范围支持新版浏览器和操作系统,但存在少数不支持平台,例如cPanel广泛支持

 具体Java代码SM2算法加解密实现Demo:

package org.example;import org.bouncycastle.asn1.gm.GMNamedCurves;import org.bouncycastle.asn1.x9.X9ECParameters;import org.bouncycastle.crypto.engines.SM2Engine;import org.bouncycastle.crypto.params.ECDomainParameters;import org.bouncycastle.crypto.params.ECPrivateKeyParameters;import org.bouncycastle.crypto.params.ECPublicKeyParameters;import org.bouncycastle.crypto.params.ParametersWithRandom;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.jce.spec.ECParameterSpec;import org.bouncycastle.jce.spec.ECPrivateKeySpec;import org.bouncycastle.jce.spec.ECPublicKeySpec;import org.bouncycastle.util.encoders.Hex;import java.math.BigInteger;import java.security.*;import java.security.spec.ECGenParameterSpec;public class SM2Utils {    public static KeyPair createECKeyPair() {        final ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");        // 获取一个椭圆曲线类型的密钥对生成器        final KeyPairGenerator kpg;        try {            kpg = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());            kpg.initialize(sm2Spec, new SecureRandom());            return kpg.generateKeyPair();        } catch (Exception e) {            e.printStackTrace();            return null;        }    }    public static String encrypt(String publicKeyHex, String data) {        return encrypt(getECPublicKeyByPublicKeyHex(publicKeyHex), data, 1);    }    public static String encrypt(BCECPublicKey publicKey, String data, int modeType) {        //加密模式        SM2Engine.Mode mode = SM2Engine.Mode.C1C3C2;        if (modeType != 1) {            mode = SM2Engine.Mode.C1C2C3;        }        ECParameterSpec ecParameterSpec = publicKey.getParameters();        ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),                ecParameterSpec.getG(), ecParameterSpec.getN());        ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters(publicKey.getQ(), ecDomainParameters);         SM2Engine sm2Engine = new SM2Engine(mode);        sm2Engine.init(true, new ParametersWithRandom(ecPublicKeyParameters, new SecureRandom()));        byte[] arrayOfBytes = null;        try {            byte[] in = data.getBytes("utf-8");                    arrayOfBytes = sm2Engine.processBlock(in, 0, in.length);        } catch (Exception e) {            System.out.println("SM2加密时出现异常:" + e.getMessage());            e.printStackTrace();        }        return Hex.toHexString(arrayOfBytes);    }    public static String decrypt(String privateKeyHex, String cipherData) {        return decrypt(getBCECPrivateKeyByPrivateKeyHex(privateKeyHex), cipherData, 1);    }    public static String decrypt(BCECPrivateKey privateKey, String cipherData, int modeType) {        //解密模式        SM2Engine.Mode mode = SM2Engine.Mode.C1C3C2;        if (modeType != 1)            mode = SM2Engine.Mode.C1C2C3;               byte[] cipherDataByte = Hex.decode(cipherData);        ECParameterSpec ecParameterSpec = privateKey.getParameters();        ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),                ecParameterSpec.getG(), ecParameterSpec.getN());        ECPrivateKeyParameters ecPrivateKeyParameters = new ECPrivateKeyParameters(privateKey.getD(),                ecDomainParameters);        SM2Engine sm2Engine = new SM2Engine(mode);        sm2Engine.init(false, ecPrivateKeyParameters);        String result = null;        try {            byte[] arrayOfBytes = sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length);            result = new String(arrayOfBytes, "utf-8");        } catch (Exception e) {            System.out.println("SM2解密时出现异常" + e.getMessage());        }        return result;    }     private static X9ECParameters x9ECParameters = GMNamedCurves.getByName("sm2p256v1");    private static ECParameterSpec ecDomainParameters = new ECParameterSpec(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());    public static BCECPublicKey getECPublicKeyByPublicKeyHex(String pubKeyHex) {          if (pubKeyHex.length() > 128) {            pubKeyHex = pubKeyHex.substring(pubKeyHex.length() - 128);        }        String stringX = pubKeyHex.substring(0, 64);        String stringY = pubKeyHex.substring(stringX.length());        BigInteger x = new BigInteger(stringX, 16);        BigInteger y = new BigInteger(stringY, 16);          ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(x9ECParameters.getCurve().createPoint(x, y), ecDomainParameters);            return new BCECPublicKey("EC", ecPublicKeySpec, BouncyCastleProvider.CONFIGURATioN);    }    public static BCECPrivateKey getBCECPrivateKeyByPrivateKeyHex(String privateKeyHex) {        BigInteger d = new BigInteger(privateKeyHex, 16);        ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(d, ecDomainParameters);        return new BCECPrivateKey("EC", ecPrivateKeySpec, BouncyCastleProvider.CONFIGURATION);    }    public static void main(String[] args) {        String publicKeyHex = null;        String privateKeyHex = null;        KeyPair keyPair = createECKeyPair();        PublicKey publicKey = keyPair.getPublic();        if (publicKey instanceof BCECPublicKey) {            //获取65字节非压缩缩的十六进制公钥串(0x04)            publicKeyHex = Hex.toHexString(((BCECPublicKey) publicKey).getQ().getEncoded(false));            System.out.println("SM2公钥:" + publicKeyHex);        }        PrivateKey privateKey = keyPair.getPrivate();        if (privateKey instanceof BCECPrivateKey) {            //获取32字节十六进制私钥串            privateKeyHex = ((BCECPrivateKey) privateKey).getD().toString(16);            System.out.println("SM2私钥:" + privateKeyHex);        }                String data = "=========需要加密的数据=========";        //将十六进制公钥串转换为 BCECPublicKey 公钥对象        String encryptData = encrypt(publicKeyHex, data);        System.out.println("加密结果:" + encryptData);                //将十六进制私钥串转换为 BCECPrivateKey 私钥对象        data = decrypt(privateKeyHex, encryptData);        System.out.println("解密结果:" + data);    }}

pom依赖引入 :

      org.bouncycastle      bcprov-jdk15to18      1.68

 

来源地址:https://blog.csdn.net/oh_coding/article/details/129182595

--结束END--

本文标题: 国密SM2: 加解密实现 java代码完整示例

本文链接: https://lsjlt.com/news/383991.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作