import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.*; import java.util.Arrays; import java.util.Base64; /** * @Description SM4实现工具类(支持cbc-密文分组链接方式的工具类) */ public class Sm4Util2 { static { Security.addProvider(new BouncyCastleProvider()); } public static final String IV = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; public static final String ALGORITHM_NAME = "SM4"; public static final String CBC_NAME = "SM4/CBC/PKCS5Padding"; public static final String DEFAULT_KEY = "random_seed"; // 128-32位16进制;256-64位16进制 public static final int DEFAULT_KEY_SIZE = 128; static { Security.addProvider(new BouncyCastleProvider()); } public static byte[] generateKey() throws NoSuchAlgorithmException, NoSuchProviderException { return generateKey(DEFAULT_KEY, DEFAULT_KEY_SIZE); } public static byte[] generateKey(String seed) throws NoSuchAlgorithmException, NoSuchProviderException { return generateKey(seed, DEFAULT_KEY_SIZE); } public static byte[] generateKey(String seed, int keySize) throws NoSuchAlgorithmException, NoSuchProviderException { KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME); SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); if (null != seed && !"".equals(seed)) { random.setSeed(seed.getBytes()); } kg.init(keySize, random); return kg.generateKey().getEncoded(); } /** * @description 加密 */ public static byte[] encrypt(String algorithmName, byte[] key, byte[] iv, byte[] data) throws Exception { return sm4core(algorithmName, Cipher.ENCRYPT_MODE, key, iv, data); } public static String encryptCbc(String key, String data) throws Exception { String encryptStr=""; byte[] keyy = ByteUtils.fromHexString(key); System.out.println("Sm4Util2的加密 key 为:" + key); byte[] ivv = ByteUtils.fromHexString(IV); System.out.println("Sm4Util2的加密 iv 为:" + IV); byte[] dataa = data.getBytes(StandardCharsets.UTF_8); // String encryptStr = new String(dataa, StandardCharsets.UTF_8); // System.out.println("Sm4Util2的加密 data 为:" + encryptStr); byte[] encrypted = sm4core(CBC_NAME,Cipher.ENCRYPT_MODE, keyy, ivv, dataa); System.out.println("encrypted string: " + Base64.getEncoder().encodeToString(encrypted)); encryptStr=Base64.getEncoder().encodeToString(encrypted); return encryptStr; } /** * @description 解密 */ public static byte[] decrypt(String algorithmName, byte[] key, byte[] iv, byte[] data) throws Exception { return sm4core(algorithmName, Cipher.DECRYPT_MODE, key, iv, data); } public static String decryptCbc(String key, String data) throws Exception { String decryptStr=""; byte[] keyy = ByteUtils.fromHexString(key); System.out.println("Sm4Util2的解密 key 为:" + key); byte[] ivv = ByteUtils.fromHexString(IV); System.out.println("Sm4Util2的解密 iv 为:" + IV); System.out.println("Sm4Util2要解密 data 为:" + data); byte[] original= new byte[0]; try { original = Base64.getDecoder().decode(data); } catch (Exception e) { e.printStackTrace(); } byte[] decrypted=sm4core(CBC_NAME, Cipher.DECRYPT_MODE, keyy, ivv, original); decryptStr = new String(decrypted,StandardCharsets.UTF_8); System.out.println("decrypted string 是: " + decryptStr); return decryptStr; } private static byte[] sm4core(String algorithmName, int type, byte[] key, byte[] iv, byte[] data) throws Exception { Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME); Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME); if (algorithmName.contains("/ECB/")) { cipher.init(type, sm4Key); } else { IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); cipher.init(type, sm4Key, ivParameterSpec); } return cipher.doFinal(data); } }