【工具】国密SM4算法加解密
2023-04-18 16:16:11 时间
SM4是一种分组密码算法,其分组长度为128位(即16字节,4字),密钥长度也为128位(即16字节,4字)。其加解密过程采用了32轮迭代机制(与DES、AES类似),每一轮需要一个轮密钥(与DES、AES类似)。
1.引入密码算法相关包
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.59</version>
</dependency>
2.工具类
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import org.apache.tomcat.util.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class SM4Util {
static {
Security.addProvider(new BouncyCastleProvider());
}
private static final String ENCODING = "UTF-8";
public static final String ALGORITHM_NAME = "SM4";
// 加密算法/分组加密模式/分组填充方式
// PKCS5Padding-以8个字节为一组进行分组加密
// 定义分组加密模式使用:PKCS5Padding
public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding";
// 128-32位16进制;256-64位16进制
public static final int DEFAULT_KEY_SIZE = 128;
private static final BouncyCastleProvider PROVIDER = new BouncyCastleProvider();
// 自定义密钥或使用generateKey生成密钥
public static String secret_key = "fjeWEhu41223Tycd";
/**
* 自动生成密钥
* @explain
* @return
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
*/
public static byte[] generateKey() throws Exception {
return generateKey(DEFAULT_KEY_SIZE);
}
/**
* @explain
* @param keySize
* @return
* @throws Exception
*/
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();
}
/**
* 加密
*
* @param content 加密的字符串
* @param encryptKey key值
*/
public static String encrypt(String content) throws Exception {
//设置Cipher对象
Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_ECB_PADDING, PROVIDER);
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(secret_key.getBytes(), ALGORITHM_NAME));
//调用doFinal
byte[] b = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
// 转base64
return Base64.encodeBase64String(b);
}
/**
* 解密
*
* @param encryptStr 解密的字符串
* @param decryptKey 解密的key值
*/
public static String decrypt(String encryptStr) throws Exception{
//base64格式的key字符串转byte
byte[] decodeBase64 = Base64.decodeBase64(encryptStr);
//设置Cipher对象
Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_ECB_PADDING, PROVIDER);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(secret_key.getBytes(), ALGORITHM_NAME));
//调用doFinal解密
byte[] decryptBytes = cipher.doFinal(decodeBase64);
return new String(decryptBytes);
}
public static void main(String[] args) {
try {
System.out.println(encrypt("123qwe++"));
System.out.println(encrypt("rwertw"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.出现的问题
maven打包部署没有出现问题,
但是可运维的jar包,打包后执行报错JCE cannot authenticate the provider BC,查询了问题,发现还需要配置jdk
进入jdk安装目录下jre/lib/security,编辑文件java.security
添加配置:11是序号,前面对应递增就行,如果你最后是9,这里需要改成10.
security.provider.11=org.bouncycastle.jce.provider.BouncyCastleProvider
然后从项目maven库里拷贝使用到的 bcprov-jdk15on-1.59.jar,复制到jre/lib/ext/目录下
之后重启项目(一定不能忘记这一步)
相关文章
- 【技术种草】cdn+轻量服务器+hugo=让博客“云原生”一下
- CLB运维&运营最佳实践 ---访问日志大洞察
- vnc方式登陆服务器
- 轻松学排序算法:眼睛直观感受几种常用排序算法
- 十二个经典的大数据项目
- 为什么使用 CDN 内容分发网络?
- 大数据——大数据默认端口号列表
- Weld 1.1.5.Final,JSR-299 的框架
- JavaFX 2012:彻底开源
- 提升as3程序性能的十大要点
- 通过凸面几何学进行独立于边际的在线多类学习
- 利用行动影响的规律性和部分已知的模型进行离线强化学习
- ModelLight:基于模型的交通信号控制的元强化学习
- 浅谈Visual Source Safe项目分支
- 基于先验知识的递归卡尔曼滤波的代理人联合状态和输入估计
- 结合网络结构和非线性恢复来提高声誉评估的性能
- 最佳实践丨云开发CloudBase多环境管理实践
- TimeVAE:用于生成多变量时间序列的变异自动编码器
- 具有线性阈值激活的神经网络:结构和算法
- 内网渗透之横向移动 -- 从域外向域内进行密码喷洒攻击