|
500精币
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import sun.misc.BASE64Decoder;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Arrays;
import java.util.Base64;
public class TestEncrypt {
static {
try {
Security.addProvider(new BouncyCastleProvider());
} catch (Exception e) {
}
}
/**
* 秘钥空间大小.
*/
public static final int SM4_KEY_SIZE = 128;
/**
* 默认秘钥空间为128,Key的长度是16.
*/
public static final int SM4_KEY_LENGTH = 16;
/**
* 算法编号.
*/
public static final String SM4_NAME = "SM4";
/**
* CBC模式串.
*/
public static final String SM4_NAME_ECB = "SM4/CBC/PKCS5Padding";
/**
* 首次加密初始向量.
*/
protected static final byte[] SM4_KEY_IV = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31};
/**
* 生成SM4算法的KEY.
*
* @Return 生成的SM4秘钥.
* @throws Exception .
*/
public String generateSm4Key() {
try {
return Base64.getEncoder().encodeToString(generateSm4Key(SM4_KEY_SIZE));
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
}
return null;
}
/**
* 生成SM4算法的KEY.
*
* @param sm4Key 指定秘钥空间大小.
* @return 生成的SM4秘钥.
* @throws Exception .
*/
private static byte[] generateSm4Key(int sm4Key) throws NoSuchAlgorithmException, NoSuchProviderException {
KeyGenerator keyGenerator = KeyGenerator.getInstance(SM4_NAME, BouncyCastleProvider.PROVIDER_NAME);
keyGenerator.init(sm4Key, new SecureRandom());
return keyGenerator.generateKey().getEncoded();
}
/**
* 对文本内容进行加密.
*
* @param plainText 待加密明文内容.
* @param sm4Key SM4秘钥.
* @return 加密的密文.
*/
public String encodeText(String plainText, String sm4Key) {
try {
return encodeByCbc(plainText, sm4Key);
} catch (NoSuchProviderException | BadPaddingException | NoSuchAlgorithmException | IllegalBlockSizeException | NoSuchPaddingException e) {
}
return null;
}
/**
* 对文本密文进行解密.
*
* @param cipherText 待解密密文.
* @param sm4Key SM4秘钥.
* @return 解密的明文.
* @throws Exception .
*/
public String decodeText(String cipherText, String sm4Key) {
return decodeByCbc(cipherText, sm4Key);
}
/**
* 对字节数组内容进行加密.
*
* @param sm4Key SM4秘钥.
* @return 加密的密文.
*/
public byte[] encodeBytes(byte[] plainBytes, String sm4Key) {
byte[] sm4KeyBytes = null;
byte[] cipherBytes = null;
try {
// 秘钥位数处理转换.
sm4Key = sm4KeyPadding(sm4Key);
// base64格式秘钥转换:sm4Key to byte[].
sm4KeyBytes = Base64.getDecoder().decode(sm4Key);
// 使用转换后的原文和秘钥进行加密操作.
cipherBytes = encodeCbcPadding(plainBytes, sm4KeyBytes);
// 对加密结果使用base64进行编码:cipherBytes to Base64格式.
} catch (Exception ex) {
cipherBytes = new byte[]{1};
}
return cipherBytes;
}
/**
* 对字节数组密文进行解密.
*
* @param sm4Key SM4秘钥.
* @return 解密的明文.
*/
public byte[] decodeBytes(byte[] cipherBytes, String sm4Key) {
byte[] keyBts = null;
byte[] plainBytes = new byte[0];
try {
// 秘钥位数处理转换.
sm4Key = sm4KeyPadding(sm4Key);
// base64格式秘钥转换:sm4Key to byte[].
keyBts = Base64.getDecoder().decode(sm4Key);
// 使用转换后的密文和秘钥进行解密操作
plainBytes = decryptCbcPadding(cipherBytes, keyBts);
} catch (Exception ex) {
plainBytes = new byte[]{0};
}
return plainBytes;
}
/**
* 基于CBC模式进行SM4加密.
*
* @param plainText 待加密明文.
* @param sm4Key Base64格式秘钥.
* @return 加密后Base64格式密文.
* @throws Exception 可能异常.
*/
private String encodeByCbc(String plainText, String sm4Key) throws NoSuchProviderException, BadPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, NoSuchPaddingException {
String cipherText = "";
byte[] sm4KeyBytes = null;
byte[] plainBytes = null;
byte[] cipherBytes = null;
try {
// 秘钥位数处理转换.
sm4Key = sm4KeyPadding(sm4Key);
// base64格式秘钥转换:sm4Key to byte[].
sm4KeyBytes = Base64.getDecoder().decode(sm4Key);
// String格式原文转换:plainText to byte[].
plainBytes = plainText.getBytes(StandardCharsets.UTF_8);
// 使用转换后的原文和秘钥进行加密操作.
cipherBytes = encodeCbcPadding(plainBytes, sm4KeyBytes);
// 对加密结果使用base64进行编码:cipherBytes to Base64格式.
cipherText = Base64.getEncoder().encodeToString(cipherBytes);
} catch (RuntimeException ex) {
cipherText = "";
}
return cipherText;
}
/**
* SM4算法的CBC模式加密.
*
* @param plainBytes 待加密明文.
* @param sm4Key Base64格式秘钥.
* @return 加密后byte[]格式密文.
* @throws Exception 可能异常.
*/
private byte[] encodeCbcPadding(byte[] plainBytes, byte[] sm4Key) throws NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, BadPaddingException, IllegalBlockSizeException {
Cipher cipher = generateSm4EcbCipher(SM4_NAME_ECB, Cipher.ENCRYPT_MODE, sm4Key);
return cipher.doFinal(plainBytes);
}
/**
* 基于CBC模式进行SM4解密.
*
* @param cipherText 待解密密文.
* @param sm4Key Base64格式秘钥.
* @return 解密后原文.
* @throws Exception 可能异常.
*/
private String decodeByCbc(String cipherText, String sm4Key) {
String plainText = "";
byte[] keyBts = null;
byte[] cipherBts = null;
byte[] plainBytes = null;
// 使用转换后的密文和秘钥进行解密操作
try {
// 秘钥位数处理转换.
sm4Key = sm4KeyPadding(sm4Key);
// base64格式秘钥转换:sm4Key to byte[].
BASE64Decoder decoder = new BASE64Decoder();
//sm4KeyBytes = Base64.getDecoder().decode(sm4Key.getBytes(StandardCharsets.UTF_8));
keyBts = decoder.decodeBuffer(sm4Key);
//keyBts = Base64.getDecoder().decode(sm4Key);
// base64格式密文转换:cipherText to byte[].
cipherBts = decoder.decodeBuffer(cipherText);
plainBytes = decryptCbcPadding(cipherBts, keyBts);
} catch (NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException | IOException e) {
e.printStackTrace();
}
// 将解密结果转换为字符串:srcData to String.
plainText = new String(plainBytes, StandardCharsets.UTF_8);
return plainText;
}
/**
* SM4算法的CBC模式解密.
*
* @param sm4Key Base64格式秘钥.
* @return 解密后byte[]格式密文.
* @throws Exception 可能异常.
*/
private byte[] decryptCbcPadding(byte[] cipherBytes, byte[] sm4Key) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException {
Cipher cipher = generateSm4EcbCipher(SM4_NAME_ECB, Cipher.DECRYPT_MODE, sm4Key);
return cipher.doFinal(cipherBytes);
}
/**
* 针对错误的秘钥进行补齐或除余操作.
*
* @param sm4Key Base64格式秘钥.
* @return 补齐或除余后的结果.
*/
private static String sm4KeyPadding(String sm4Key) {
String targetSm4Key = null;
byte[] sm4KeyBytes = null;
byte[] targetSm4KeyBts = null;
try {
if (null == sm4Key) {
targetSm4Key = "";
return targetSm4Key;
}
BASE64Decoder decoder = new BASE64Decoder();
//sm4KeyBytes = Base64.getDecoder().decode(sm4Key.getBytes(StandardCharsets.UTF_8));
sm4KeyBytes = decoder.decodeBuffer(sm4Key);
//System.out.println(new String(decoder.decodeBuffer(sm4Key), "UTF-8"));
// 若Key超长,则除去多余的内容.
if (sm4KeyBytes.length > SM4_KEY_LENGTH) {
targetSm4KeyBts = new byte[SM4_KEY_LENGTH];
System.arraycopy(sm4KeyBytes, 0, targetSm4KeyBts, 0, SM4_KEY_LENGTH);
}
// 若Key较短,则补齐多余的内容.
else if (sm4KeyBytes.length < SM4_KEY_LENGTH) {
targetSm4KeyBts = new byte[SM4_KEY_LENGTH];
System.arraycopy(sm4KeyBytes, 0, targetSm4KeyBts, 0, sm4KeyBytes.length);
Arrays.fill(targetSm4KeyBts, sm4KeyBytes.length, SM4_KEY_LENGTH, (byte) 1);
} else {
targetSm4KeyBts = sm4KeyBytes;
}
} catch (Exception ex) {
ex.printStackTrace();
// log.error("SM4Util.sm4KeyPadding.", ex);
targetSm4KeyBts = new byte[0];
}
// 以Base64格式返回Key.
return Base64.getEncoder().encodeToString(targetSm4KeyBts);
}
/**
* 生成SM4算法实例.
*
* @param sm4Name 算法名称.
* @param sm4Mode 加密模式.
* @param sm4Key 秘钥内容.
* @return SM4算法实例.
* @throws Exception 可能异常.
*/
private Cipher generateSm4EcbCipher(String sm4Name, int sm4Mode, byte[] sm4Key) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException {
Cipher cipher = Cipher.getInstance(sm4Name, BouncyCastleProvider.PROVIDER_NAME);
Key secretKey = new SecretKeySpec(sm4Key, SM4_NAME);
IvParameterSpec ivParameterSpec = new IvParameterSpec(SM4_KEY_IV);
try {
cipher.init(sm4Mode, secretKey, ivParameterSpec);
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return cipher;
}
public static void main(String[] args) {
String data = "{\n" +
" \"entId\": \"0b094b92804a4a3aa6f611b863f4080f\",\n" +
" \"wasteId\": \"34a9849ce7d14358915325f94bd0c61c\",\n" +
" \"quantity\": 0.003 ,\n" +
" \"unit\": \"吨\",\n" +
" \"sourceId\": \"a238ef2e6f744944ba1ab9a69bbcadd5\",\n" +
" \"produceDate\": \"2021-07-01 01:02:02\",\n" +
" \"userName\": \"测试用户0714\",\n" +
" \"iotToken\": \"a238ef2e6f744944ba1ab9a69bbcadd5\",\n" +
" \"remark\": \"测试数据\"\n" +
" }";
String key = "903B2CBD-D669-47E3-A6D9-94655C72B3BB";
TestEncrypt encrypt = new TestEncrypt();
String encryptData = encrypt.encodeText(data, key);
System.out.println("encryptData(拷贝到请求体中):" + encryptData);
String plainText = encrypt.decodeText(encryptData, key);
System.out.println("plainText:" + plainText);
}
}
|
|