5 changed files with 294 additions and 23 deletions
@ -0,0 +1,184 @@ |
|||
package com.epmet.commons.tools.utils.api.yt; |
|||
|
|||
|
|||
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.SecretKeySpec; |
|||
import java.security.*; |
|||
import java.util.Arrays; |
|||
|
|||
/** |
|||
* sm4加密算法工具类 |
|||
* |
|||
* @explain sm4加密、解密与加密结果验证 可逆算法 |
|||
* @Autor:jingyao |
|||
*/ |
|||
public class TestMs4 { |
|||
static { |
|||
Security.addProvider(new BouncyCastleProvider()); |
|||
} |
|||
|
|||
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; |
|||
|
|||
/** |
|||
* 生成ECB暗号 |
|||
* |
|||
* @param algorithmName 算法名称 |
|||
* @param mode 模式 |
|||
* @param key |
|||
* @return |
|||
* @throws Exception |
|||
* @explain ECB模式(电子密码本模式:Electronic codebook) |
|||
*/ |
|||
private static Cipher generateEcbCipher(String algorithmName, int mode, byte[] key) throws Exception { |
|||
Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME); |
|||
Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME); |
|||
cipher.init(mode, sm4Key); |
|||
return cipher; |
|||
} |
|||
|
|||
/** |
|||
* 自动生成密钥 |
|||
* |
|||
* @return |
|||
* @throws NoSuchAlgorithmException |
|||
* @throws NoSuchProviderException |
|||
* @explain |
|||
*/ |
|||
public static byte[] generateKey() throws Exception { |
|||
return generateKey(DEFAULT_KEY_SIZE); |
|||
} |
|||
|
|||
|
|||
//加密******************************************
|
|||
|
|||
/** |
|||
* @param keySize |
|||
* @return |
|||
* @throws Exception |
|||
* @explain 系统产生秘钥 |
|||
*/ |
|||
public static byte[] generateKey(int keySize) throws Exception { |
|||
KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME); |
|||
kg.init(keySize, new SecureRandom()); |
|||
return kg.generateKey().getEncoded(); |
|||
} |
|||
|
|||
/** |
|||
* sm4加密 |
|||
* |
|||
* @param hexKey 16进制密钥(忽略大小写) |
|||
* @param paramStr 待加密字符串 |
|||
* @return 返回16进制的加密字符串 |
|||
* @throws Exception |
|||
* @explain 加密模式:ECB 密文长度不固定,会随着被加密字符串长度的变化而变化 |
|||
*/ |
|||
public static String encryptEcb(String hexKey, String paramStr) throws Exception { |
|||
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); |
|||
return cipherText; |
|||
} |
|||
|
|||
/** |
|||
* 加密模式之Ecb |
|||
* |
|||
* @param key |
|||
* @param data |
|||
* @return |
|||
* @throws Exception |
|||
*/ |
|||
public static byte[] encrypt_Ecb_Padding(byte[] key, byte[] data) throws Exception { |
|||
Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, key);//声称Ecb暗号,通过第二个参数判断加密还是解密
|
|||
return cipher.doFinal(data); |
|||
} |
|||
|
|||
//解密****************************************
|
|||
|
|||
/** |
|||
* sm4解密 |
|||
* |
|||
* @param hexKey 16进制密钥 |
|||
* @param cipherText 16进制的加密字符串(忽略大小写) |
|||
* @return 解密后的字符串 |
|||
* @throws Exception |
|||
* @explain 解密模式:采用ECB |
|||
*/ |
|||
public static String decryptEcb(String hexKey, String cipherText) throws Exception { |
|||
// 用于接收解密后的字符串
|
|||
String decryptStr = ""; |
|||
// hexString-->byte[]
|
|||
byte[] keyData = ByteUtils.fromHexString(hexKey); |
|||
// hexString-->byte[]
|
|||
byte[] cipherData = ByteUtils.fromHexString(cipherText); |
|||
// 解密
|
|||
byte[] srcData = decrypt_Ecb_Padding(keyData, cipherData); |
|||
// byte[]-->String
|
|||
decryptStr = new String(srcData, ENCODING); |
|||
return decryptStr; |
|||
} |
|||
|
|||
/** |
|||
* 解密 |
|||
* |
|||
* @param key |
|||
* @param cipherText |
|||
* @return |
|||
* @throws Exception |
|||
* @explain |
|||
*/ |
|||
public static byte[] decrypt_Ecb_Padding(byte[] key, byte[] cipherText) throws Exception { |
|||
Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, key);//生成Ecb暗号,通过第二个参数判断加密还是解密
|
|||
return cipher.doFinal(cipherText); |
|||
} |
|||
|
|||
/** |
|||
* 校验加密前后的字符串是否为同一数据 |
|||
* |
|||
* @param hexKey 16进制密钥(忽略大小写) |
|||
* @param cipherText 16进制加密后的字符串 |
|||
* @param paramStr 加密前的字符串 |
|||
* @return 是否为同一数据 |
|||
* @throws Exception |
|||
* @explain |
|||
*/ |
|||
public static boolean verifyEcb(String hexKey, String cipherText, String paramStr) throws Exception { |
|||
// 用于接收校验结果
|
|||
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); |
|||
return flag; |
|||
} |
|||
|
|||
public static void main(String[] args) throws Exception { |
|||
String text = "5d22ea44c7599a48f0d4446b1b7fbb4bb8353922df437d39c3a38549c0f2549cbd021ada00a8be83027ae06203c3daea2eedc5bd0875c7e509c7049045c5349577f2c21bcec328a5ea0bf341191e5bdba978566dddd16f1cf1928ff5cbd826dd33289fb45a8a04585f1f24ab04f59426371a5a0a0f2ee3e7b00d2bdfba7810524ce4c33130eda077546fa4c4191d0117f7a44e1cadac6c69a7d437653be1f958a459e0f025d471e09ab4636c38013032948ffb0827040ed6f3436be090f545186928a7b0b2bfc65782452606607ce8555ba130caacad73998da704428a07276a2699889c9872eebba5de8b72cdbe88705483293b00ab3ecb3aa57d283a4ecab40b71bc0a10e9ec626f07b2293255349fb2270d37e81c5c3d0de0b0f0706ed1872f60f039ce2e51effc39aef9747d67457e072cf3170a9c19589c1bab1a7d9d80"; |
|||
String s = TestMs4.decryptEcb("dbcff4c9f4774e6cb56080f279149d59", text); |
|||
System.out.println(s); |
|||
} |
|||
|
|||
} |
|||
|
Loading…
Reference in new issue