package com.dji.sample.droneairport.utils;
|
|
import org.bouncycastle.crypto.engines.SM4Engine;
|
import org.bouncycastle.crypto.params.KeyParameter;
|
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
|
import org.bouncycastle.crypto.paddings.PKCS7Padding;
|
|
import java.nio.charset.StandardCharsets;
|
import java.security.SecureRandom;
|
import java.util.Arrays;
|
import java.util.Base64;
|
|
public class SM4Util {
|
|
|
/**
|
* 生成一个随机的SM4加密密钥。
|
*
|
* SM4算法是一种对称加密算法,其密钥长度为128位(16字节)。
|
* 本方法使用安全随机数生成器生成一个16字节的随机值作为SM4密钥,
|
* 并将其转换为十六进制字符串格式以便于使用和存储。
|
*
|
* @return 返回一个表示SM4密钥的十六进制字符串。
|
*/
|
public static String generateSM4Key() {
|
SecureRandom secureRandom = new SecureRandom();
|
byte[] sm4Key = new byte[16]; // SM4 密钥长度为 128 位(16 字节)
|
secureRandom.nextBytes(sm4Key);
|
String key = bytesToHex(sm4Key);
|
return key;
|
}
|
|
|
private static String bytesToHex(byte[] bytes) {
|
StringBuilder sb = new StringBuilder();
|
for (byte b : bytes) {
|
sb.append(String.format("%02x", b));
|
}
|
return sb.toString();
|
}
|
/**
|
* 使用SM4算法加密输入数据。
|
*
|
* @param key 加密密钥,应符合SM4算法的密钥长度要求。
|
* @param input 待加密的输入数据。
|
* @return 加密后的数据,以Base64编码形式表示。
|
*/
|
public static String encrypt(byte[] key, byte[] input) {
|
// 创建并初始化SM4加密器
|
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new SM4Engine(), new PKCS7Padding());
|
cipher.init(true, new KeyParameter(key)); // ECB模式下不需要IV
|
|
// 用于存储加密后的数据
|
byte[] output = new byte[cipher.getOutputSize(input.length)];
|
// 处理输入数据,进行加密
|
int length = cipher.processBytes(input, 0, input.length, output, 0);
|
|
// 完成加密过程,处理可能剩余的数据
|
try {
|
length += cipher.doFinal(output, length);
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
|
// 使用Base64编码加密后的字节数组,并返回
|
String encoded = Base64.getEncoder().encodeToString(Arrays.copyOf(output, length));
|
return encoded;
|
}
|
|
|
/**
|
* 使用SM4算法对输入数据进行解密
|
*
|
* @param key 密钥字节数组,用于解密数据
|
* @param input 待解密的字节数组
|
* @return 解密后的字节数组
|
*/
|
public static byte[] decrypt(byte[] key, byte[] input) {
|
// 创建基于SM4算法的缓冲分组密码对象
|
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new SM4Engine(), new PKCS7Padding());
|
// 初始化密码对象为解密模式,并设置密钥参数
|
cipher.init(false, new KeyParameter(key)); // ECB模式下不需要IV
|
// 根据输入数据长度计算解密后的字节数组长度
|
byte[] output = new byte[cipher.getOutputSize(input.length)];
|
// 处理字节数组,将输入数据解密到输出字节数组中
|
int length = cipher.processBytes(input, 0, input.length, output, 0);
|
try {
|
// 完成最终的解密操作,并将长度累加到已处理字节数组中
|
length += cipher.doFinal(output, length);
|
} catch (Exception e) {
|
// 捕获并处理解密过程中的异常
|
e.printStackTrace();
|
}
|
// 返回解密后的字节数组
|
return Arrays.copyOf(output, length);
|
}
|
|
public static String decrypt(String keys,String secert){
|
byte[] key = keys.getBytes(StandardCharsets.UTF_8);
|
byte[] ming= Base64.getDecoder().decode(secert);
|
byte[] text=decrypt(key,ming);
|
return new String(text, StandardCharsets.UTF_8);
|
}
|
|
public static String encrypt(String keys, String input){
|
byte[] key = keys.getBytes(StandardCharsets.UTF_8);
|
return encrypt(key,input.getBytes());
|
}
|
|
public static void main(String[] args) {
|
byte[] key = "jsimjrby3wqb7dbq".getBytes(StandardCharsets.UTF_8); // 16字节密钥
|
|
// 原始明文
|
String plaintext = "{ \"deviceid\": \"1581F6QAD241500BDZ3J\", \"status\": 1 }";
|
|
String secert =encrypt(key,plaintext.getBytes());
|
// System.out.println(secert);
|
|
|
byte[] ming= Base64.getDecoder().decode(secert);
|
byte[] text=decrypt(key,ming);
|
// System.out.println(new String(text, StandardCharsets.UTF_8));
|
// System.out.println("封装"+encrypt("jsimjrby3wqb7dbq",plaintext));
|
// System.out.println("封装"+decrypt("jsimjrby3wqb7dbq","9LFnVDdqleTOFcBJT7TSxs788zPH8PicodLb5634SsixHrKNX+ZAgwODPZxvWFNQ"));
|
String encryptedBase64 = encrypt(key, plaintext.getBytes(StandardCharsets.UTF_8));
|
// System.out.println("Encrypted (Base64): " + encryptedBase64);
|
System.out.println(generateSM4Key());
|
// 直接解密
|
byte[] decoded = Base64.getDecoder().decode(encryptedBase64);
|
byte[] decrypted = decrypt(key, decoded);
|
|
// // 输出结果
|
// System.out.println("Plaintext: " + plaintext);
|
// System.out.println("Decrypted: " + new String(decrypted, StandardCharsets.UTF_8));
|
}
|
}
|