本来想用 hutool 的国密算法工具 SmUtil,报这个错 java.lang.NoSuchMethodError: org.bouncycastle.crypto.engines.SM2Engine <init>(Lorg/bouncycaSTLe/asn1/DEREncodableVector;)V

项目里不能修改 bouncycastle 的版本,既然 hutool 底层也是用的 bouncycastle 实现,就干脆直接用 bouncycastle 做一套国密算法吧。。

<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15to18</artifactId><version>1.69</version>
</dependency>

SM2实现

package com.ty.bbc.utils.gm;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.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;import java.math.BigInteger;
import java.security.*;
import java.security.spec.ECGenParameterSpec;public class SM2Util {/*** 生成 SM2 公私钥对* @return* @throws NoSuchAlgorithmException* @throws InvalidAlgorithmParameterException*/public KeyPair geneSM2KeyPair() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {final ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");// 获取一个椭圆曲线类型的密钥对生成器final KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());// 使用SM2参数初始化生成器kpg.initialize(sm2Spec);// 获取密钥对KeyPair keyPair = kpg.generateKeyPair();return keyPair;}/*** 获取私钥(16进制字符串,头部不带00长度共64)* @param privateKey 私钥* @return*/public String getPriKeyHexString(PrivateKey privateKey){BCECPrivateKey s=(BCECPrivateKey)privateKey;String priKeyHexString = Hex.toHexString(s.getD().toByteArray());if(null!= priKeyHexString && priKeyHexString.length()==66 && "00".equals(priKeyHexString.substring(0,2))){return priKeyHexString.substring(2);}return priKeyHexString;}/*** 获取公钥(16进制字符串,头部带04长度共130)* @param publicKey* @return*/public String getPubKeyHexString(PublicKey publicKey){BCECPublicKey p=(BCECPublicKey)publicKey;return Hex.toHexString(p.getQ().getEncoded(false));}/*** SM2加密算法* @param publicKey 公钥* @param data      明文数据* @return*/public String encrypt(PublicKey publicKey, String data){BCECPublicKey p=(BCECPublicKey)publicKey;return encrypt(Hex.toHexString(p.getQ().getEncoded(false)), data);}/*** SM2解密算法* @param privateKey  私钥(16进制字符串)* @param cipherData  密文数据* @return*/public String decrypt(PrivateKey privateKey, String cipherData) {BCECPrivateKey s=(BCECPrivateKey)privateKey;return decrypt(Hex.toHexString(s.getD().toByteArray()), cipherData);}/*** SM2加密算法* @param pubKeyHexString  公钥(16进制字符串)* @param data             明文数据* @return*/public String encrypt(String pubKeyHexString, String data) {// 获取一条SM2曲线参数X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");// 构造ECC算法参数,曲线方程、椭圆曲线G点、大整数NECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());//提取公钥点ECPoint pukPoint = sm2ECParameters.getCurve().decodePoint(Hex.decode(pubKeyHexString));// 公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥, 04的时候,可以去掉前面的04ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(pukPoint, domainParameters);SM2Engine sm2Engine = new SM2Engine();// 设置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 priKeyHexString  私钥(16进制字符串)* @param cipherData       密文数据* @return*/public String decrypt(String priKeyHexString, String cipherData) {// 使用BC库加解密时密文以04开头,传入的密文前面没有04则补上if (!cipherData.startsWith("04")){cipherData = "04" + cipherData;}byte[] cipherDataByte = Hex.decode(cipherData);//获取一条SM2曲线参数X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");//构造domain参数ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());BigInteger privateKeyD = new BigInteger(priKeyHexString, 16);ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(privateKeyD, domainParameters);SM2Engine sm2Engine = new SM2Engine();// 设置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 void main(String[] args) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {String M="encryption standard";System.out.println("\n明文:"+ M);SM2Util sm2 = new SM2Util();KeyPair keyPair = sm2.geneSM2KeyPair();PublicKey publicKey = keyPair.getPublic();String pubKeyHexString = sm2.getPubKeyHexString(publicKey);System.out.println("公钥:"+ pubKeyHexString);PrivateKey privateKey = keyPair.getPrivate();String priKeyHexString = sm2.getPriKeyHexString(privateKey);System.out.println("私钥:"+ priKeyHexString);String cipherData = sm2.encrypt(pubKeyHexString, M);System.out.println("密文:" + cipherData);String text=sm2.decrypt(priKeyHexString, cipherData);System.out.println("解密:"+text);}
}

SM3实现

package com.ty.bbc.utils.gm;import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.util.encoders.Hex;/*** @author jiangzhe* @create 2022/8/23 14:13*/
public class SM3Util {public String hash1(String data){return Hex.toHexString(hash2(data));}public byte[] hash2(String data){SM3Digest sm3Digest=new SM3Digest();byte[] srcData = data.getBytes();sm3Digest.update(srcData,0,srcData.length);byte[] hash = new byte[sm3Digest.getDigestSize()];sm3Digest.doFinal(hash, 0);return hash;}public static void main(String[] args) {SM3Util sm3 = new SM3Util();String data = "abcd";System.out.println("摘要:" + sm3.hash1(data));//输出 82ec580fe6d36ae4f81cae3c73f4a5b3b5a09c943172dc9053c69fd8e18dca1e 就说明符合SM3算法要求}
}

SM4实现

package com.ty.bbc.utils.gm;import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.bouncycastle.util.encoders.Hex;import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Arrays;public class SM4Util {static {Security.addProvider(new BouncyCastleProvider());}private static final String ENCODING = "UTF-8";public static final String ALGORITHM_NAME = "SM4";// 加密算法/分组加密模式/分组填充方式// PKCS5Padding-以8个字节为一组进行分组加密// 定义分组加密模式使用:PKCS5Paddingpublic static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding";// 128-32位16进制;256-64位16进制public static final int DEFAULT_KEY_SIZE = 128;/*** 自动生成密钥(16进制字符串,长度32)** @return* @explain*/public static String generateKey() throws Exception {return Hex.toHexString(generateKey(DEFAULT_KEY_SIZE));}/*** @param keySize* @return* @throws Exception* @explain*/public static byte[] generateKey(int keySize) throws Exception {KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);kg.init(keySize, new SecureRandom());return kg.generateKey().getEncoded();}/*** 生成ECB暗号** @param algorithmName 算法名称* @param mode          模式* @param key* @return* @throws Exception* @explain ECB模式(电子密码本模式:Electronic codebook)*/private static Cipher generateEcbCipher(String algorithmName, int mode, byte[] key) throws Exception {Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);cipher.init(mode, sm4Key);return cipher;}/*** sm4加密** @param hexKey   16进制密钥(忽略大小写)* @param paramStr 待加密字符串* @return 返回16进制的加密字符串* @explain 加密模式:ECB* 密文长度不固定,会随着被加密字符串长度的变化而变化*/public static String encryptEcb(String hexKey, String paramStr) {try {String cipherText = "";// 16进制字符串-->byte[]byte[] keyData = ByteUtils.fromHexString(hexKey);// String-->byte[]byte[] srcData = paramStr.getBytes(ENCODING);// 加密后的数组byte[] cipherArray = encrypt_Ecb_Padding(keyData, srcData);// byte[]-->hexStringcipherText = ByteUtils.toHexString(cipherArray);return cipherText;} catch (Exception e) {return paramStr;}}/*** 加密模式之Ecb** @param key* @param data* @return* @throws Exception* @explain*/public static byte[] encrypt_Ecb_Padding(byte[] key, byte[] data) throws Exception {Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, key);return cipher.doFinal(data);}/*** sm4解密** @param hexKey     16进制密钥* @param cipherText 16进制的加密字符串(忽略大小写)* @return 解密后的字符串* @throws Exception* @explain 解密模式:采用ECB*/public static String decryptEcb(String hexKey, String cipherText) {// 用于接收解密后的字符串String decryptStr = "";// hexString-->byte[]byte[] keyData = ByteUtils.fromHexString(hexKey);// hexString-->byte[]byte[] cipherData = ByteUtils.fromHexString(cipherText);// 解密byte[] srcData = new byte[0];try {srcData = decrypt_Ecb_Padding(keyData, cipherData);// byte[]-->StringdecryptStr = new String(srcData, ENCODING);} catch (Exception e) {e.printStackTrace();}return decryptStr;}/*** 解密** @param key* @param cipherText* @return* @throws Exception* @explain*/public static byte[] decrypt_Ecb_Padding(byte[] key, byte[] cipherText) throws Exception {Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, key);return cipher.doFinal(cipherText);}/*** 校验加密前后的字符串是否为同一数据** @param hexKey     16进制密钥(忽略大小写)* @param cipherText 16进制加密后的字符串* @param paramStr   加密前的字符串* @return 是否为同一数据* @throws Exception* @explain*/public static boolean verifyEcb(String hexKey, String cipherText, String paramStr) throws Exception {// 用于接收校验结果boolean flag = false;// hexString-->byte[]byte[] keyData = ByteUtils.fromHexString(hexKey);// 将16进制字符串转换成数组byte[] cipherData = ByteUtils.fromHexString(cipherText);// 解密byte[] decryptData = decrypt_Ecb_Padding(keyData, cipherData);// 将原字符串转换成byte[]byte[] srcData = paramStr.getBytes(ENCODING);// 判断2个数组是否一致flag = Arrays.equals(decryptData, srcData);return flag;}public static void main(String[] args) {try {String json = "{\"name\":\"jz\"}";System.out.println("明文:" + json);// 生成32位16进制密钥String key = SM4Util.generateKey();System.out.println("密钥:" + key);String cipher = SM4Util.encryptEcb(key, json);System.out.println("密文:" + cipher);System.out.println("数据是否有效:" + SM4Util.verifyEcb(key, cipher, json));String res = SM4Util.decryptEcb(key, cipher);System.out.println("解密后数据:" + res);} catch (Exception e) {e.printStackTrace();}}
}

SM2 SM3 SM4 国密版本,基于bouncycastle 实现相关推荐

  1. javascript sm2 sm3 sm4 国密库

    前面研究了iOS端的sm2,sm3,sm4,sm9,zuc国密.前端后期也会接入国密库,所以研究了下JavaScript的国密.如果需要知道算法原理的可以查看我之前的博客,或者看我的github上也有 ...

  2. python商用_python实现sm2和sm4国密(国家商用密码)算法的示例

    GMSSL模块介绍 GmSSL是一个开源的加密包的python实现,支持SM2/SM3/SM4等国密(国家商用密码)算法.项目采用对商业应用友好的类BSD开源许可证,开源且可以用于闭源的商业应用. 安 ...

  3. SM2 (含SM3、SM4)国密算法工具QT版,彻底搞懂sm2算法的使用

    网上有很多网友问算法SM2怎么使用?什么是压缩公钥和非压缩公钥?xB和yB这参数是什么?怎么使用SM2做加解密?如何签名和验签?有没有工具来验证下? 这里分享个自己用QT造的一个小工具,简单好用,同时 ...

  4. php gmssl,支持国密SM2/SM3/SM4/SM9/ZUC/SSL的密码工具箱GmSSL

    GmSSL概述 GmSSL是一个开源的密码工具箱,支持SM2/SM3/SM4/SM9/ZUC等国密(国家商用密码)算法.SM2国密数字证书及基于SM2证书的SSL/TLS安全通信协议,支持国密硬件密码 ...

  5. 国密算法SM1/SM2/SM3/SM4

    原创不易,转载请注明出处. 国密算法由国家密码局发布,今天大概介绍4中国密算法,分别是SM1,SM2,SM3,SM4.他们之间异同通过下表展示. 算法名称 算法分类 算法是否公开 明文最大长度(bit ...

  6. 国密SM1\ SM2\ SM3\ SM4\ SSF33算法和国际RSA算法的对应关系

    转载自https://blog.csdn.net/hcnetbee/article/details/53692579,部分内容和排版稍作修改. 国密算法由国家密码局发布,包含SM1\ SM2\ SM3 ...

  7. 国密SM2,SM3,SM4的前后台(js和java)加解密写法

    目录 SM2加解密 js java SM3加密 js java sm3前后台(js/java)加密不一致原因 SM4加解密 js java 之前做一个项目的时候需要用到国密SM2,SM3,SM4的加解 ...

  8. java sm_Java国密SM2/SM3/SM4及证书

    1. 使用BC库1.59版本已经可以支持国密算法SM2/SM3/SM4,某大神写的详细测试例子:https://github.com/ZZMarquis/gmhelper 2. 制作证书参考网上资料简 ...

  9. OpenSSL 1.1.1 新特性: 全面支持国密SM2/SM3/SM4加密算法

    OpenSSL项目最近6个月添加了许多新特性, 包括对中国SM2/SM3/SM4算法的支持: SM2椭圆曲线: https://github.com/openssl/openssl/pull/4793 ...

  10. 国密算法 SM2 SM3 SM4 及密钥生成

    国密算法 SM2 SM3 SM4 方式一:SM2密钥在线生成 SM2密钥在线生成工具 如果你没线下生成工具,可用下面2种线上生成方式之一: 1. sm2密钥在线生成(const.net.cn) 2.  ...

最新文章

  1. (数据库系统概论|王珊)第七章数据库设计:习题
  2. BZOJ 2818GCD
  3. bzoj 4942 整数 思考记录
  4. Eclipse tomcat先启动成功,然后再报超时原因之一
  5. Spring security3入门(转)
  6. 【人脸识别】基于matlab GUI PCA人脸二维码识别(带面板)【含Matlab源码 754期】
  7. 中考计算机wps题怎么做,WPS与ScienceWord联合制作理科试卷 -电脑资料
  8. Android开发 手机开发者模式
  9. python elif invalid syntax_Python错误集锦:if和elif语句提示:SyntaxError: invalid syntax
  10. [2001年写的小说]星际争霸之外传
  11. css横排文字光影效果_css3模糊发光文字动画特效
  12. 聊一聊Java如何接入招行一网通支付功能
  13. 模拟CS (警察和匪徒)
  14. Transformer15
  15. 计算机网络自顶向下学习摘要
  16. HA集群强制进行Active/Standby切换的命令
  17. 2023最新SSM计算机毕业设计选题大全(附源码+LW)之java基于流浪宠物领养系统8xg84
  18. H3CSE园区-组播转发机制
  19. 大数据在5G应用场景下有哪些示范项目?
  20. 5G物联网组网架构-网络

热门文章

  1. 借了你的爱,用我一辈子来还
  2. poj - 2586 - Y2K Accounting Bug
  3. Renew 、Revive 、Renovate、Update、Refresh区别
  4. 中国K12在线教育用户消费行为报告
  5. JAVA7-6 约分最简分式 (15 分)
  6. 【离散数学】集合的基数
  7. 旧电脑很卡怎么重新安装电脑系统?
  8. 很开心你能来,不遗憾你走开
  9. 钉钉机器人智能提醒_使用钉钉机器人定时发送消息
  10. 美国电话号码格式化的Objective-C代码