| | |
| | | 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); |
| | | } |
| | | |
| | |
| | | byte[] key = "jsimjrby3wqb7dbq".getBytes(StandardCharsets.UTF_8); // 16字节密钥 |
| | | |
| | | // 原始明文 |
| | | String plaintext = "{\n" + |
| | | "\"regioncode\": \"650000\",\n" + |
| | | "\"deviceid\": \"dh11111111111\",\n" + |
| | | "\"brand\": \"大疆\",\n" + |
| | | "\"model\": \"M3D\",\n" + |
| | | "\"longitude\": 120.6670,\n" + |
| | | "\"latitude\": 30.4567,\n" + |
| | | "\"height\": 45,\n" + |
| | | "\"radius\": 10000\n" + |
| | | "}\n"; |
| | | String plaintext = "{ \"deviceid\": \"1581F6QAD241500BDZ3J\", \"status\": 1 }"; |
| | | |
| | | String secert =encrypt(key,plaintext.getBytes()); |
| | | System.out.println(secert); |
| | | // 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","hello")); |
| | | System.out.println("封装"+decrypt("jsimjrby3wqb7dbq","MkzmRdHSy/pB4sdTjNHb4ngG0q7Z+vWzNKdJxJFkhw4Y9tI8R9sapL6ECLyVnKZwiZbmVQFtn+sT294nCVdskK8TUx7CCI3qo21d9I4ONl+XAYnlDCtEa8KSFK3CB3/D9zRt96zEDkv31Av2rdAJW9O7Le1Z13wWGmsEqHjjrXLv5jd/Cop6+BB9+lqDRlhx+ubNOFdUgJALe4wHjZPCMdE0ob44Hx+1iLg7m/WJQWc=")); |
| | | // 直接加密 |
| | | // 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); |