importorg.apache.commons.codec.binary.Hex;importorg.bouncycastle.jce.provider.BouncyCastleProvider;importorg.bouncycastle.pqc.math.linearalgebra.ByteUtils;importjavax.crypto.Cipher;importjavax.crypto.KeyGenerator;importjavax.crypto.spec.SecretKeySpec;importjava.security.Key;importjava.security.SecureRandom;importjava.security.Security;importjava.util.Arrays;public classSm4Util {static{
Security.addProvider(newBouncyCastleProvider());
}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;/*** 自动生成密钥
*
*@return* @explain*/
public static String generateKey() throwsException {return new String(Hex.encodeHex(generateKey(DEFAULT_KEY_SIZE),false));
}/***@paramkeySize
*@return*@throwsException
* @explain*/
public static byte[] generateKey(int keySize) throwsException {
KeyGenerator kg=KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);
kg.init(keySize,newSecureRandom());returnkg.generateKey().getEncoded();
}/*** 生成ECB暗号
*
*@paramalgorithmName 算法名称
*@parammode 模式
*@paramkey
*@return*@throwsException
* @explain ECB模式(电子密码本模式:Electronic codebook)*/
private static Cipher generateEcbCipher(String algorithmName, int mode, byte[] key) throwsException {
Cipher cipher=Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);
Key sm4Key= newSecretKeySpec(key, ALGORITHM_NAME);
cipher.init(mode, sm4Key);returncipher;
}/*** sm4加密
*
*@paramhexKey 16进制密钥(忽略大小写)
*@paramparamStr 待加密字符串
*@return返回16进制的加密字符串
* @explain 加密模式:ECB
* 密文长度不固定,会随着被加密字符串长度的变化而变化*/
public staticString encryptEcb(String hexKey, String paramStr) {try{
String cipherText= "";//16进制字符串-->byte[]
byte[] keyData =ByteUtils.fromHexString(hexKey);//String-->byte[]
byte[] srcData =paramStr.getBytes(ENCODING);//加密后的数组
byte[] cipherArray =encrypt_Ecb_Padding(keyData, srcData);//byte[]-->hexString
cipherText =ByteUtils.toHexString(cipherArray);returncipherText;
}catch(Exception e) {returnparamStr;
}
}/*** 加密模式之Ecb
*
*@paramkey
*@paramdata
*@return*@throwsException
* @explain*/
public static byte[] encrypt_Ecb_Padding(byte[] key, byte[] data) throwsException {
Cipher cipher=generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, key);returncipher.doFinal(data);
}/*** sm4解密
*
*@paramhexKey 16进制密钥
*@paramcipherText 16进制的加密字符串(忽略大小写)
*@return解密后的字符串
*@throwsException
* @explain 解密模式:采用ECB*/
public staticString decryptEcb(String hexKey, String cipherText) {//用于接收解密后的字符串
String decryptStr = "";//hexString-->byte[]
byte[] keyData =ByteUtils.fromHexString(hexKey);//hexString-->byte[]
byte[] cipherData =ByteUtils.fromHexString(cipherText);//解密
byte[] srcData = new byte[0];try{
srcData=decrypt_Ecb_Padding(keyData, cipherData);//byte[]-->String
decryptStr = newString(srcData, ENCODING);
}catch(Exception e) {
e.printStackTrace();
}returndecryptStr;
}/*** 解密
*
*@paramkey
*@paramcipherText
*@return*@throwsException
* @explain*/
public static byte[] decrypt_Ecb_Padding(byte[] key, byte[] cipherText) throwsException {
Cipher cipher=generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, key);returncipher.doFinal(cipherText);
}/*** 校验加密前后的字符串是否为同一数据
*
*@paramhexKey 16进制密钥(忽略大小写)
*@paramcipherText 16进制加密后的字符串
*@paramparamStr 加密前的字符串
*@return是否为同一数据
*@throwsException
* @explain*/
public static boolean verifyEcb(String hexKey, String cipherText, String paramStr) throwsException {//用于接收校验结果
boolean flag = false;//hexString-->byte[]
byte[] keyData =ByteUtils.fromHexString(hexKey);//将16进制字符串转换成数组
byte[] cipherData =ByteUtils.fromHexString(cipherText);//解密
byte[] decryptData =decrypt_Ecb_Padding(keyData, cipherData);//将原字符串转换成byte[]
byte[] srcData =paramStr.getBytes(ENCODING);//判断2个数组是否一致
flag =Arrays.equals(decryptData, srcData);returnflag;
}public static voidmain(String[] args) {try{
String json= "BF7B6BD7C1204BC4F3C87D235692DE9DBF7B6BD7C1204BC4F3C87D235692DE9DBF7B6BD7C1204BC4F3C87D235692DE9D";
System.out.println("加密前源数据————" +json);//生成32位16进制密钥
String key =Sm4Util.generateKey();
System.out.println(key+ "-----生成key");
String cipher=Sm4Util.encryptEcb(key, json);
System.out.println("加密串---" +cipher);
System.out.println(Sm4Util.verifyEcb(key, cipher, json));
json=Sm4Util.decryptEcb(key, cipher);
System.out.println("解密后数据---" +json);
}catch(Exception e) {
e.printStackTrace();
}
}
}