package org.sxkj.common.utils; import org.bouncycastle.crypto.InvalidCipherTextException; import org.bouncycastle.crypto.engines.SM4Engine; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher; import org.bouncycastle.crypto.paddings.PKCS7Padding; import org.sxkj.common.utils.sm3.SM2SignUtil; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.security.SecureRandom; import java.util.Arrays; import java.util.Base64; public class SM4Util { /** * 生成一个随机的SM4加密密钥。 * * SM4算法是一种对称加密算法,其密钥长度为128位(16字节)。 * 本方法使用安全随机数生成器生成一个16字节的随机值作为SM4密钥, * 并将其转换为十六进制字符串格式以便于使用和存储。 * * @return 返回一个表示SM4密钥的十六进制字符串。 */ public static byte[] generateSM4Key() { SecureRandom secureRandom = new SecureRandom(); byte[] sm4Key = new byte[16]; // SM4 密钥长度为 128 位(16 字节) secureRandom.nextBytes(sm4Key); return sm4Key; } public static String strSM4Key() { SecureRandom secureRandom = new SecureRandom(); byte[] sm4Key = new byte[8]; // SM4 密钥长度为 128 位(16 字节) secureRandom.nextBytes(sm4Key); String key = bytesToHex(sm4Key); return key; } private static String bytesToHex(byte[] bytes) { StringBuilder sb = new StringBuilder(); for (byte b : bytes) { sb.append(String.format("%02x", b)); } return sb.toString(); } /** * 使用SM4算法加密输入数据。 * * @param key 加密密钥,应符合SM4算法的密钥长度要求。 * @param input 待加密的输入数据。 * @return 加密后的数据,以Base64编码形式表示。 */ public static String encrypt(byte[] key, byte[] input) { // 创建并初始化SM4加密器 PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new SM4Engine(), new PKCS7Padding()); cipher.init(true, new KeyParameter(key)); // ECB模式下不需要IV // 用于存储加密后的数据 byte[] output = new byte[cipher.getOutputSize(input.length)]; // 处理输入数据,进行加密 int length = cipher.processBytes(input, 0, input.length, output, 0); // 完成加密过程,处理可能剩余的数据 try { length += cipher.doFinal(output, length); } catch (Exception e) { e.printStackTrace(); } // 使用Base64编码加密后的字节数组,并返回 String encoded = Base64.getEncoder().encodeToString(Arrays.copyOf(output, length)); return encoded; } /** * 使用SM4算法对输入数据进行解密 * * @param key 密钥字节数组,用于解密数据 * @param input 待解密的字节数组 * @return 解密后的字节数组 */ public static byte[] decrypt(byte[] key, byte[] input) { // 创建基于SM4算法的缓冲分组密码对象 PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new SM4Engine(), new PKCS7Padding()); // 初始化密码对象为解密模式,并设置密钥参数 cipher.init(false, new KeyParameter(key)); // ECB模式下不需要IV // 根据输入数据长度计算解密后的字节数组长度 byte[] output = new byte[cipher.getOutputSize(input.length)]; // 处理字节数组,将输入数据解密到输出字节数组中 int length = cipher.processBytes(input, 0, input.length, output, 0); try { // 完成最终的解密操作,并将长度累加到已处理字节数组中 length += cipher.doFinal(output, length); } catch (Exception e) { // 捕获并处理解密过程中的异常 e.printStackTrace(); } // 返回解密后的字节数组 return Arrays.copyOf(output, length); } public static String decrypt(byte[] keys,String secert){ byte[] ming= Base64.getDecoder().decode(secert); byte[] text=decrypt(keys,ming); return new String(text, StandardCharsets.UTF_8); } public static String encrypt(byte[] keys, String input){ return encrypt(keys,input.getBytes()); } public static String encrypt(String keys, String input){ return encrypt(keys.getBytes(),input.getBytes()); } }