001package top.cenze.utils.crypt;
002
003import org.bouncycastle.jce.provider.BouncyCastleProvider;
004import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
005
006import javax.crypto.Cipher;
007import javax.crypto.KeyGenerator;
008import javax.crypto.spec.SecretKeySpec;
009import java.security.Key;
010import java.security.SecureRandom;
011import java.security.Security;
012import java.util.Arrays;
013
014/**
015 * SM4国密加密解密工具
016 *
017 * @author chengze
018 * @date 2023-11-14 22:36
019 */
020public class SM4Util {
021
022    private static final String ENCODING = "UTF-8";
023    public static final String ALGORIGTHM_NAME = "SM4";//密钥名称
024    public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS7Padding";//密码的分组方式SM4/ECB/PKCS7Padding
025    public static final int DEFAULT_KEY_SIZE = 128;//默认的key值长度128
026
027    public SM4Util() {
028    }
029
030    static {
031        Security.addProvider(new BouncyCastleProvider());
032    }
033
034    /**
035     *  @Description:生成ecb暗号
036     */
037    private static Cipher generateEcbCipher(String algorithmName, int mode, byte[] key) throws Exception {
038        Cipher cipher = Cipher.getInstance(algorithmName,BouncyCastleProvider.PROVIDER_NAME);
039        Key sm4Key = new SecretKeySpec(key, ALGORIGTHM_NAME);
040        cipher.init(mode, sm4Key);
041        return cipher;
042    }
043
044    /**
045     *  @Description:自动生成密钥
046     */
047    public static String generateKey() throws Exception {
048        return generateKey(DEFAULT_KEY_SIZE);
049    }
050
051    public static String generateKey(int keySize) throws Exception {
052        KeyGenerator kg = KeyGenerator.getInstance(ALGORIGTHM_NAME, BouncyCastleProvider.PROVIDER_NAME);
053        kg.init(keySize, new SecureRandom());
054        return ByteUtils.toHexString(kg.generateKey().getEncoded());
055    }
056
057
058    /**
059     *  @Description:加密
060     */
061    public static String encryptEcb(String hexKey, String paramStr, String charset) throws Exception {
062        String cipherText = "";
063        if (null != paramStr && !"".equals(paramStr)) {
064            byte[] keyData = ByteUtils.fromHexString(hexKey);
065            charset = charset.trim();
066            if (charset.length() <= 0) {
067                charset = ENCODING;
068            }
069            byte[] srcData = paramStr.getBytes(charset);
070            byte[] cipherArray = encrypt_Ecb_Padding(keyData, srcData);
071            cipherText = ByteUtils.toHexString(cipherArray);
072        }
073        return cipherText;
074    }
075
076    /**
077     *  @Description:加密模式之ecb
078     */
079    public static byte[] encrypt_Ecb_Padding(byte[] key, byte[] data) throws Exception {
080        Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, key);
081        byte[] bs = cipher.doFinal(data);
082        return bs;
083    }
084
085    /**
086     *  @Description:sm4解密
087     */
088    public static String decryptEcb(String hexKey, String cipherText, String charset) throws Exception {
089        String decryptStr = "";
090        byte[] keyData = ByteUtils.fromHexString(hexKey);
091        byte[] cipherData = ByteUtils.fromHexString(cipherText);
092        byte[] srcData = decrypt_Ecb_Padding(keyData, cipherData);
093        charset = charset.trim();
094        if (charset.length() <= 0) {
095            charset = ENCODING;
096        }
097        decryptStr = new String(srcData, charset);
098        return decryptStr;
099    }
100
101    /**
102     *  @Description:解密
103     */
104    public static byte[] decrypt_Ecb_Padding(byte[] key, byte[] cipherText) throws Exception {
105        Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, key);
106        return cipher.doFinal(cipherText);
107    }
108
109    /**
110     *  @Description:密码校验
111     */
112    public static boolean verifyEcb(String hexKey, String cipherText, String paramStr) throws Exception {
113        boolean flag = false;
114        byte[] keyData = ByteUtils.fromHexString(hexKey);
115        byte[] cipherData = ByteUtils.fromHexString(cipherText);
116        byte[] decryptData = decrypt_Ecb_Padding(keyData,cipherData);
117        byte[] srcData = paramStr.getBytes(ENCODING);
118        flag = Arrays.equals(decryptData,srcData);
119        return flag;
120    }
121
122//    /**
123//     *  @Description:测试类
124//     */
125//    public static void main(String[] args) {
126//        try {
127//            String  keyByte = generateKey(DEFAULT_KEY_SIZE);
128//
129//            String json = "     中国 人";
130//            // 自定义的32位16进制密钥
131//            String key = generateKey();
132//            key = "a0710e8fa0856ee38c48d6d796356658";
133//            System.out.println(key);
134//            String cipher = Sm4Utils.encryptEcb(key, json,ENCODING);
135//            System.out.println(cipher);
136//            System.out.println(Sm4Utils.verifyEcb(key, cipher, json));
137//            json = Sm4Utils.decryptEcb(key, cipher,ENCODING);
138//            System.out.println(json);
139//        } catch (Exception e) {
140//            e.printStackTrace();
141//        }
142//    }
143}