| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- package com.ruoyi.common.utils;
- import com.ruoyi.common.config.Sm4Config;
- import org.bouncycastle.jce.provider.BouncyCastleProvider;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
- import javax.crypto.Cipher;
- import javax.crypto.spec.SecretKeySpec;
- import java.nio.charset.StandardCharsets;
- import java.security.Security;
- import java.util.Base64;
- /**
- * SM4加密算法工具类
- * 使用固定密钥,直接从配置文件读取
- * 兼容Java 8版本
- */
- @Component
- public class SM4Util {
- private final byte[] key;
- static {
- // 添加BouncyCastleProvider
- Security.addProvider(new BouncyCastleProvider());
- }
- // 算法名称
- private static final String ALGORITHM_NAME = "SM4";
- private static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding";
- @Autowired
- public SM4Util(Sm4Config sm4Config) {
- // 从配置文件中读取密钥并转换为字节数组
- this.key = hexStringToBytes(sm4Config.getSecretKey());
- if (this.key.length != 16) {
- throw new IllegalArgumentException("SM4密钥必须是16字节(32位十六进制字符串)");
- }
- }
- /**
- * 将十六进制字符串转换为字节数组(兼容Java 8)
- */
- private byte[] hexStringToBytes(String hexString) {
- if (hexString == null || hexString.length() % 2 != 0) {
- throw new IllegalArgumentException("无效的十六进制字符串");
- }
- int len = hexString.length();
- byte[] data = new byte[len / 2];
- for (int i = 0; i < len; i += 2) {
- data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
- + Character.digit(hexString.charAt(i + 1), 16));
- }
- return data;
- }
- /**
- * 将字节数组转换为十六进制字符串(兼容Java 8)
- */
- private String bytesToHexString(byte[] bytes) {
- StringBuilder hexString = new StringBuilder();
- for (byte b : bytes) {
- String hex = Integer.toHexString(0xff & b);
- if (hex.length() == 1) {
- hexString.append('0');
- }
- hexString.append(hex);
- }
- return hexString.toString().toUpperCase();
- }
- /**
- * 加密字符串
- *
- * @param data 待加密的字符串
- * @return Base64编码的加密结果
- */
- public String encrypt(String data) {
- if (StringUtils.isNull(data)) return null;
- try {
- Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_ECB_PADDING, BouncyCastleProvider.PROVIDER_NAME);
- SecretKeySpec secretKeySpec = new SecretKeySpec(key, ALGORITHM_NAME);
- cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
- byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
- return Base64.getEncoder().encodeToString(encrypted);
- } catch (Exception e) {
- throw new RuntimeException("SM4加密失败", e);
- }
- }
- /**
- * 解密字符串
- *
- * @param encryptedData Base64编码的加密数据
- * @return 解密后的原始字符串
- */
- public String decrypt(String encryptedData) {
- if (StringUtils.isNull(encryptedData)) return null;
- try {
- Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_ECB_PADDING, BouncyCastleProvider.PROVIDER_NAME);
- SecretKeySpec secretKeySpec = new SecretKeySpec(key, ALGORITHM_NAME);
- cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
- byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData);
- byte[] decrypted = cipher.doFinal(encryptedBytes);
- return new String(decrypted, StandardCharsets.UTF_8);
- } catch (Exception e) {
- throw new RuntimeException("SM4解密失败", e);
- }
- }
- /**
- * 加密字节数组
- *
- * @param data 待加密的字节数组
- * @return 加密后的字节数组
- */
- public byte[] encrypt(byte[] data) {
- try {
- Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_ECB_PADDING, BouncyCastleProvider.PROVIDER_NAME);
- SecretKeySpec secretKeySpec = new SecretKeySpec(key, ALGORITHM_NAME);
- cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
- return cipher.doFinal(data);
- } catch (Exception e) {
- throw new RuntimeException("SM4加密失败", e);
- }
- }
- /**
- * 解密字节数组
- *
- * @param encryptedData 加密的字节数组
- * @return 解密后的原始字节数组
- */
- public byte[] decrypt(byte[] encryptedData) {
- try {
- Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_ECB_PADDING, BouncyCastleProvider.PROVIDER_NAME);
- SecretKeySpec secretKeySpec = new SecretKeySpec(key, ALGORITHM_NAME);
- cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
- return cipher.doFinal(encryptedData);
- } catch (Exception e) {
- throw new RuntimeException("SM4解密失败", e);
- }
- }
- /**
- * 获取当前使用的密钥(十六进制格式)
- */
- public String getKeyHex() {
- return bytesToHexString(key);
- }
- /**
- * 验证加密解密功能是否正常
- */
- public boolean selfCheck() {
- try {
- String testData = "SM4测试数据123";
- String encrypted = encrypt(testData);
- String decrypted = decrypt(encrypted);
- return testData.equals(decrypted);
- } catch (Exception e) {
- return false;
- }
- }
- }
|