JAVA集成国密SM4

JAVA集成国密SM4加解密

  • 一、pom配置
  • 二、代码集成
    • 2.1、目录结构
    • 2.2、源码
    • 2.3、测试
  • 三、遇到的坑
    • 3.1、秘钥长度
    • 3.2、转码问题
  • 四、相关链接

国密算法概述:https://blog.csdn.net/qq_38254635/article/details/131801527

SM4对称算法
SM4 无线局域网标准的分组数据算法。对称加密,密钥长度和分组长度均为128位

一、pom配置

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

二、代码集成

2.1、目录结构

在这里插入图片描述

2.2、源码

ConfigBean.java

package com.secret.sm4;public class ConfigBean {/*** 秘钥空间大小*/public static final int SM4_KEY_SIZE = 128;/*** 算法编号*/public static final String ALGORITHM_NAME  = "SM4";/*** 首次加密初始向量  01030507090B0D0F11131517191B1D1F*/public static final byte[] SM4_KEY_IV = { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 };/*** ECB模式串*/public static final String ALGORITHM_ECB_PADDING = "SM4/ECB/PKCS5Padding";/*** CBC模式串*/public static final String ALGORITHM_CBC_PADDING = "SM4/CBC/PKCS5Padding";}

ProviderSingleton.java

package com.secret.sm4;import org.bouncycastle.jce.provider.BouncyCastleProvider;public class ProviderSingleton {private static BouncyCastleProvider instance = null;private ProviderSingleton() {}private static synchronized void syncInit() {if (instance == null) {instance = new BouncyCastleProvider();}}public static BouncyCastleProvider getInstance() {if (instance == null) {syncInit();}return instance;}}

SecretCommon.java

package com.secret.sm4;import org.apache.tomcat.util.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;/*** SM4分组对称密码算法(对称算法)* SM4分组密码算法是我国自主设计的分组对称密码算法,用于实现数据的加密/解密运算,以保证数据和信息的机密性。* 要保证一个对称密码算法的安全性的基本条件是其具备足够的密钥长度,SM4算法与AES算法具有相同的密钥长度分组长度128比特,因此在安全性上高于3DES算法。*/
public class SecretCommon {static {Security.addProvider(new BouncyCastleProvider());}/*** 生成秘钥*/public static String generateKey() throws NoSuchAlgorithmException {return ByteUtils.toHexString(generateKeyByte(ConfigBean.SM4_KEY_SIZE, ProviderSingleton.getInstance()));}/*** 生成秘钥*/public static String generateKeyBC() throws NoSuchProviderException, NoSuchAlgorithmException {return ByteUtils.toHexString(generateKeyByte(ConfigBean.SM4_KEY_SIZE, BouncyCastleProvider.PROVIDER_NAME));}public static byte[] generateKeyByte(int keySize, String var) throws NoSuchAlgorithmException, NoSuchProviderException {KeyGenerator keyGenerator = KeyGenerator.getInstance(ConfigBean.ALGORITHM_NAME, var);keyGenerator.init(keySize, new SecureRandom());return keyGenerator.generateKey().getEncoded();}public static byte[] generateKeyByte(int keySize, BouncyCastleProvider var) throws NoSuchAlgorithmException {KeyGenerator keyGenerator = KeyGenerator.getInstance(ConfigBean.ALGORITHM_NAME, var);keyGenerator.init(keySize, new SecureRandom());return keyGenerator.generateKey().getEncoded();}/*** ECB模式,加密* @param plainText 明文字符串* @param keyText 秘钥内容*/public static String encryptECB(String plainText, String keyText) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {return Base64.encodeBase64String(cipherECB(Cipher.ENCRYPT_MODE, plainText.getBytes(StandardCharsets.UTF_8), keyText.getBytes()));}/*** ECB模式,解密* @param cipherText 密文字符串* @param keyText 秘钥内容*/public static String decryptECB(String cipherText, String keyText) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {return new String(cipherECB(Cipher.DECRYPT_MODE, Base64.decodeBase64(cipherText), keyText.getBytes()));}/*** ECB模式,加解密算法基础方法* @param mode 加解密模式 Cipher.ENCRYPT_MODE 1:加密/ Cipher.DECRYPT_MODE 2:解密* @param plainByte 需加密明文内容/待解密密文内容* @param keyByte 秘钥内容*/public static byte[] cipherECB(int mode, byte[] plainByte, byte[] keyByte) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {Cipher cipher = Cipher.getInstance(ConfigBean.ALGORITHM_ECB_PADDING, ProviderSingleton.getInstance());cipher.init(mode, new SecretKeySpec(keyByte, ConfigBean.ALGORITHM_NAME));return cipher.doFinal(plainByte);}/*** CBC模式,加密* @param plainText 明文字符串* @param keyText 秘钥内容*/public static String encryptCBC(String plainText, String keyText) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {return Base64.encodeBase64String(cipherCBC(Cipher.ENCRYPT_MODE, plainText.getBytes(StandardCharsets.UTF_8), keyText.getBytes()));}/*** CBC模式,解密* @param cipherText 密文字符串* @param keyText 秘钥内容*/public static String decryptCBC(String cipherText, String keyText) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {return new String(cipherCBC(Cipher.DECRYPT_MODE, Base64.decodeBase64(cipherText), keyText.getBytes()));}/*** CBC模式,加解密算法基础方法* @param mode 加解密模式 Cipher.ENCRYPT_MODE 1:加密/ Cipher.DECRYPT_MODE 2:解密* @param plainByte 需加密明文内容/待解密密文内容* @param keyByte 秘钥内容*/public static byte[] cipherCBC(int mode, byte[] plainByte, byte[] keyByte) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {Cipher cipher = Cipher.getInstance(ConfigBean.ALGORITHM_CBC_PADDING, ProviderSingleton.getInstance());cipher.init(mode, new SecretKeySpec(keyByte, ConfigBean.ALGORITHM_NAME), new IvParameterSpec(ConfigBean.SM4_KEY_IV));return cipher.doFinal(plainByte);}}

Utils.java

package com.secret.sm4;import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;public class Utils {/*** 生成秘钥*/public static String generateKey() throws NoSuchAlgorithmException {return SecretCommon.generateKey().substring(0, 16);}/*** 默认加密方法(ECB)*/public static String encrypt(String plainText, String keyText) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {return encryptECB(plainText, keyText);}/*** 默认解密方法(ECB)*/public static String decrypt(String cipherText, String keyText) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {return decryptECB(cipherText, keyText);}/*** ECB模式,加密* @param plainText 明文字符串* @param keyText 秘钥内容*/public static String encryptECB(String plainText, String keyText) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {return SecretCommon.encryptECB(plainText, keyText);}/*** ECB模式,解密* @param cipherText 密文字符串* @param keyText 秘钥内容*/public static String decryptECB(String cipherText, String keyText) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {return SecretCommon.decryptECB(cipherText, keyText);}/*** CBC模式,加密* @param plainText 明文字符串* @param keyText 秘钥内容*/public static String encryptCBC(String plainText, String keyText) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {return SecretCommon.encryptCBC(plainText, keyText);}/*** CBC模式,解密* @param cipherText 密文字符串* @param keyText 秘钥内容*/public static String decryptCBC(String cipherText, String keyText) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {return SecretCommon.decryptCBC(cipherText, keyText);}}

测试类:Test.java

package com.secret.sm4;public class Test {public static void main(String[] args) throws Exception{String key = Utils.generateKey();System.out.println("生成SM4秘钥:" + key);String plainText = "Believe in yourself, you are the best";String ECBText = Utils.encrypt(plainText, key);System.out.println("ECB默认加密后密文:" + ECBText);System.out.println("ECB默认解密后明文:" + Utils.decrypt(ECBText, key));String CBCText = Utils.encryptCBC(plainText, key);System.out.println("CBC加密后密文:" + CBCText);System.out.println("CBC解密后明文:" + Utils.decryptCBC(CBCText, key));}}

2.3、测试

在这里插入图片描述
使用方法参考测试类即可。

三、遇到的坑

3.1、秘钥长度

使用KeyGenerator构建的秘钥长度太长无法使用,会提示:
在这里插入图片描述
秘钥取16位即可使用。

3.2、转码问题

在使用 ECB模式 时,加解密都会报错,头大。

加密报错如下:

Exception in thread "main" java.lang.IllegalArgumentException: Last encoded character (before the paddings if any) is a valid base 64 alphabet but not a possible value. Expected the discarded bits to be zero.at org.apache.tomcat.util.codec.binary.Base64.validateCharacter(Base64.java:429)at org.apache.tomcat.util.codec.binary.Base64.decode(Base64.java:671)at org.apache.tomcat.util.codec.binary.BaseNCodec.decode(BaseNCodec.java:362)at org.apache.tomcat.util.codec.binary.BaseNCodec.decode(BaseNCodec.java:353)at org.apache.tomcat.util.codec.binary.BaseNCodec.decode(BaseNCodec.java:379)at org.apache.tomcat.util.codec.binary.Base64.decodeBase64(Base64.java:172)at com.secret.sm4.SecretCommon.encryptECB(SecretCommon.java:64)at com.secret.sm4.Utils.encryptECB(Utils.java:39)at com.secret.sm4.Utils.encrypt(Utils.java:23)at com.secret.sm4.Test.main(Test.java:10)

在这里插入图片描述

解密报错如下:

Exception in thread "main" javax.crypto.BadPaddingException: pad block corruptedat org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher$BufferedGenericBlockCipher.doFinal(Unknown Source)at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(Unknown Source)at javax.crypto.Cipher.doFinal(Cipher.java:2165)at com.secret.sm4.SecretCommon.cipherECB(SecretCommon.java:85)at com.secret.sm4.SecretCommon.decryptECB(SecretCommon.java:73)at com.secret.sm4.Utils.decryptECB(Utils.java:48)at com.secret.sm4.Utils.decrypt(Utils.java:30)at com.secret.sm4.Test.main(Test.java:12)

在这里插入图片描述

查阅了资料才发现,是转byte[]数组的问题。

String plainText = "Believe in yourself, you are the best";
byte[] byte1 = plainText.getBytes();
byte[] byte2 = plainText.getBytes(StandardCharsets.UTF_8);
byte[] byte3 = Base64.decodeBase64(plainText);
byte[] byte4 = Hex.decode(plainText);
Base64.encodeBase64String()
new String()

测试的时候发现,同样是转byte[],不同的方法,可能结果会不一样,可以自行尝试验证。

加密的时候:
入参直接使用 getBytes()获取byte数组,返回参数使用 Base64.encodeBase64String()即可。
解密的时候:
入参使用 Base64.decodeBase64()获取byte数组,返回参数直接new String() 即可。

四、相关链接

国密算法概述:https://blog.csdn.net/qq_38254635/article/details/131801527

JAVA集成国密SM2:https://blog.csdn.net/qq_38254635/article/details/131810661

JAVA集成国密SM3:https://blog.csdn.net/qq_38254635/article/details/131810696

单例模式及多线程并发在单例模式中的影响:https://blog.csdn.net/qq_38254635/article/details/119888843

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/2601.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c++内存映射文件

概念 将一个文件直接映射到进程的进程空间中&#xff08;“映射”就是建立一种对应关系,这里指硬盘上文件的位置与进程逻辑地址空间中一块相同区域之间一 一对应,这种关系纯属是逻辑上的概念&#xff0c;物理上是不存在的&#xff09;&#xff0c;这样可以通过内存指针用读写内…

qt 32位编译 内存溢出 无法 运行在win7 32位

项目在 编译32位系统 内存溢出 设置成了x64 但是 最后在xp32位系统运行提示 在下载了n个dll之后发现这种状况无穷无尽&#xff0c;后来在查阅资料时发现可以直接打开qt安装目录下的“vcredist”文件夹&#xff0c;将对应位数的程序拷到win7电脑上&#xff0c;直接运行&…

Orleans 微软基于 Actor 的分布式框架

一、Actor模型工作原理 Actor模型是一种并发编程模型&#xff0c;它基于消息传递实现&#xff0c;是一种轻量级的并发模型。在Actor模型中&#xff0c;每个Actor都是一个独立的执行单元&#xff0c;它可以接收和发送消息&#xff0c;并且可以执行一些本地操作&#xff0c;但是不…

【ARM Cortex-M 系列 1 -- Cortex-M0, M3, M4, M7, M33 差异】

文章目录 Cortex-M 系列介绍Cortex-M0/M0 介绍Cortex-M3/M4 介绍Cortex-M7 介绍Cotex-M33 介绍 下篇文章&#xff1a;ARM Cortex-M 系列 2 – CPU 之 Cortex-M7 介绍 Cortex-M 系列介绍 Cortex-M0/M0 介绍 Cortex-M0 是 ARM 公司推出的一款微控制器&#xff08;MCU&#xff0…

网络安全在2023好入行吗?

前言 023年的今天&#xff0c;慎重进入网安行业吧&#xff0c;目前来说信息安全方向的就业对于学历的容忍度比软件开发要大得多&#xff0c;还有很多高中被挖过来的大佬。 理由很简单&#xff0c;目前来说&#xff0c;信息安全的圈子人少&#xff0c;985、211院校很多都才建…

高时空分辨率、高精度一体化预测技术之风、光、水能源自动化预测技术

能源是国民经济发展和人民生活必须的重要物质基础。在过去的200多年里&#xff0c;建立在煤炭、石油、天然气等化石燃料基础上的能源体系极大的推动了人类社会的发展。但是人类在使用化石燃料的同时&#xff0c;也带来了严重的环境污染和生态系统破坏。近年来&#xff0c;世界各…

python appium UI 自动化测试框架讨论

目录 前言&#xff1a; 框架共性总结 Auto_Analysis 权限弹窗识别 前言&#xff1a; Python Appium UI自动化测试框架是一种用于测试移动应用程序的工具&#xff0c;它结合了Python编程语言和Appium测试框架的功能。 框架共性总结 1 自动找设备 连接设备 2 自动启 appium …

《数据结构》数据结构概念,顺序表,链表

目录 1. 为什么学习数据结构&#xff1f; 2. 数据结构 2.1. 数据 2.2. 逻辑结构 2.3. 存储结构 2.4. 操作 3. 算法 3.1. 算法与程序 3.2. 算法与数据结构 3.3. 算法的特性 3.4. 如何评价一个算法的好坏 4. 线性表 4.1. 顺序表 4.2. 单向链表 4.3. 单向循环链表&…

SpringBoot使用Redis作为缓存器缓存数据的操作步骤以及避坑方案

1.非注解式实现 2.1使用之前要明确使用的业务场景 例如我们在登录时&#xff0c;可以让redis缓存验证码&#xff0c;又如在分类下显示菜品数据时&#xff0c;我们可以对分类和菜品进行缓存数据等等。 2.2导入Redis相关依赖 <dependency><groupId>org.springfra…

SpringAMQP - 消息传输时,如何提高性能?解决 SQL 注入问题?

目录 一、问题背景 二、从消息转化器根源解决问题 1.引入依赖 2.在服务生产者和消费者中都重新定义一个 MessageConverter&#xff0c;注入到 Spring 容器中 一、问题背景 在SpringAMQP的发送方法中&#xff0c;接收消息的类型是Object&#xff0c;也就是说我们可以发送任意…

DB-Engines排名公布 GBASE南大通用入围国产数据库TOP 3

什么是DB-Engines排名&#xff1f; DB-Engines排名是数据库领域的流行度榜单&#xff0c;它对全球范围内的419款数据库&#xff08;截至2023年7月&#xff09;进行排名&#xff0c;每月更新一次&#xff0c;排名越靠前&#xff0c;则表示越流行。在很多技术选型的场合&#xf…

【idea】idea全局设置Maven配置

Idea版本&#xff1a;2021.1.1 1、点击File->Close project 2、点击Customize->All settings 3、设置Maven

# Linux终端控制字符详解以及简单应用实践

Linux终端控制字符详解以及简单应用实践 文章目录 Linux终端控制字符详解以及简单应用实践1 控制字符表2 控制字符 ESC &#xff08;0x1B&#xff0c;^[&#xff09;子参数表3 控制字符 ESC &#xff08;0x1B&#xff0c;^[&#xff09;子参数表 - 字符颜色参照表4 实践&#x…

Python实现HBA混合蝙蝠智能算法优化循环神经网络分类模型(LSTM分类算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 蝙蝠算法是2010年杨教授基于群体智能提出的启发式搜索算法&#xff0c;是一种搜索全局最优解的有效方法…

2023无监督摘要顶会论文合集

2023无监督摘要顶会论文合集 写在最前面ACL-2023Aspect-aware Unsupervised Extractive Opinion Summarization 面向的无监督意见摘要&#xff08;没找到&#xff09;Unsupervised Extractive Summarization of Emotion Triggers *情绪触发(原因)的 *无监督 *抽取式 摘要&#…

DETR (DEtection TRansformer)基于自建数据集开发构建目标检测模型超详细教程

目标检测系列的算法模型可以说是五花八门&#xff0c;不同的系列有不同的理论依据&#xff0c;DETR的亮点在于它是完全端到端的第一个目标检测模型&#xff0c;DETR&#xff08;Detection Transformer&#xff09;是一种基于Transformer的目标检测模型&#xff0c;由Facebook A…

Redis 从入门到精通【进阶篇】之高可用集群(Redis Cluster)详解

文章目录 0. 前言设计目标核心概念 1. 架构设计和原理1.1. 数据分片2. 节点间通信6. 扩容和缩容 2. 总结3. Redis从入门到精通系列文章4. Redis Cluster面试题4.1. Redis Cluster如何进行扩容和缩容&#xff1f;4.2. Redis Cluster如何进行故障转移&#xff1f;4.3. Redis Clus…

【问题分析解决】git添加.gitignore后不生效问题

一&#xff0c;问题现象 在已经提交过的git管理的项目中&#xff0c;新增加一个.gitignore文件&#xff0c;或者修改.gitignore文件之后&#xff0c;新增的内容不生效。 二&#xff0c;问题原因 因为我们误解了.gitignore文件的用途&#xff0c;该文件只能作用于Untracked F…

JDK JRE JVM

JDK JRE JVM JDKJREJVM三者之间的联系三者之间的区别 JDK JDK是用于开发、编译、调试和运行Java应用程序的软件包&#xff0c;包含了Java编程语言的开发工具和Java运行时环境。JDK包括Java编译器&#xff08;javac&#xff09;、Java虚拟机&#xff08;JVM&#xff09;和Java类…

单轴机器人的结构与特点

单轴机器人是由马达驱动的移动平台&#xff0c;由滚珠螺杆和 U型线性滑轨导引构成&#xff0c;其滑座同时为滚珠螺杆的驱动螺帽及线性滑轨的导引滑块&#xff0c;可用半导体、光电、交通运输业、环保节能产业、精密工具机、机械产业、智慧自动化、生技医疗上。 相对于传统的模组…