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