复制代码
/**
* SM4加密工具类
* SM4算法是一种分组密码算法,分组长度为128位,密钥长度为128位
*/
public class SM4Util {
static {
// 加入BouncyCastle支持
Security.addProvider(new BouncyCastleProvider());
}
// 算法名称
public static final String ALGORITHM_NAME = "SM4";
// 加密算法/分组加密模式/填充方式
public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding";
public static final String ALGORITHM_NAME_CBC_PADDING = "SM4/CBC/PKCS5Padding";
// 密钥长度,128位
public static final int KEY_SIZE = 128;
/**
* 生成ECB模式的密钥
* @return 16位密钥
* @throws Exception 异常
*/
public static String generateKey() throws Exception {
KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);
kg.init(KEY_SIZE, new SecureRandom());
return ByteUtils.toHexString(kg.generateKey().getEncoded());
}
/**
* 生成CBC模式的初始化向量
* @return 16位初始化向量
*/
public static String generateIV() {
SecureRandom random = new SecureRandom();
byte[] iv = new byte[16];
random.nextBytes(iv);
return ByteUtils.toHexString(iv);
}
/**
* ECB模式加密
* @param plainText 明文
* @param key 密钥(16位十六进制字符串)
* @return 加密后的Base64字符串
* @throws Exception 异常
*/
public static String encryptEcb(String plainText, String key) throws Exception {
// 将密钥转换为字节数组
byte[] keyData = ByteUtils.fromHexString(key);
// 初始化密钥
Key secretKey = new SecretKeySpec(keyData, ALGORITHM_NAME);
// 实例化加密器
Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_ECB_PADDING, BouncyCastleProvider.PROVIDER_NAME);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
// 加密
byte[] encryptedData = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
// 返回Base64编码结果
return Base64.getEncoder().encodeToString(encryptedData);
}
/**
* ECB模式解密
* @param cipherText 加密后的Base64字符串
* @param key 密钥(16位十六进制字符串)
* @return 解密后的明文
* @throws Exception 异常
*/
public static String decryptEcb(String cipherText, String key) throws Exception {
// 解码Base64
byte[] encryptedData = Base64.getDecoder().decode(cipherText);
// 将密钥转换为字节数组
byte[] keyData = ByteUtils.fromHexString(key);
// 初始化密钥
Key secretKey = new SecretKeySpec(keyData, ALGORITHM_NAME);
// 实例化解密器
Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_ECB_PADDING, BouncyCastleProvider.PROVIDER_NAME);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
// 解密
byte[] decryptedData = cipher.doFinal(encryptedData);
return new String(decryptedData, StandardCharsets.UTF_8);
}
/**
* CBC模式加密
* @param plainText 明文
* @param key 密钥(16位十六进制字符串)
* @param iv 初始化向量(16位十六进制字符串)
* @return 加密后的Base64字符串
* @throws Exception 异常
*/
public static String encryptCbc(String plainText, String key, String iv) throws Exception {
// 将密钥和IV转换为字节数组
byte[] keyData = ByteUtils.fromHexString(key);
byte[] ivData = ByteUtils.fromHexString(iv);
// 初始化密钥和IV
Key secretKey = new SecretKeySpec(keyData, ALGORITHM_NAME);
IvParameterSpec ivParameterSpec = new IvParameterSpec(ivData);
// 实例化加密器
Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_CBC_PADDING, BouncyCastleProvider.PROVIDER_NAME);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
// 加密
byte[] encryptedData = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(encryptedData);
}
/**
* CBC模式解密
* @param cipherText 加密后的Base64字符串
* @param key 密钥(16位十六进制字符串)
* @param iv 初始化向量(16位十六进制字符串)
* @return 解密后的明文
* @throws Exception 异常
*/
public static String decryptCbc(String cipherText, String key, String iv) throws Exception {
// 解码Base64
byte[] encryptedData = Base64.getDecoder().decode(cipherText);
// 将密钥和IV转换为字节数组
byte[] keyData = ByteUtils.fromHexString(key);
byte[] ivData = ByteUtils.fromHexString(iv);
// 初始化密钥和IV
Key secretKey = new SecretKeySpec(keyData, ALGORITHM_NAME);
IvParameterSpec ivParameterSpec = new IvParameterSpec(ivData);
// 实例化解密器
Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_CBC_PADDING, BouncyCastleProvider.PROVIDER_NAME);
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
// 解密
byte[] decryptedData = cipher.doFinal(encryptedData);
return new String(decryptedData, StandardCharsets.UTF_8);
}
}