package com.ruoyi.gysl.login.util;

import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Base64;

public class SM4Demo {
    /**
     * 国密SM4，对标 DES
     */
    private static final String ALGORITHM = "SM4";
    private static final Integer KEY_SIZE = 128;

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    public static Key getKey(String algorithm, int length, String passwordType, byte[] password)
            throws NoSuchAlgorithmException {
        Key key;
        if (passwordType == null || passwordType.equals("fix")) {
            key = new SecretKeySpec(password, algorithm);
        } else {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(algorithm);
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.setSeed(password);
            keyGenerator.init(length, secureRandom);
            SecretKey secretKey = keyGenerator.generateKey();
            key = new SecretKeySpec(secretKey.getEncoded(), algorithm);
        }
        return key;
    }

    public static Cipher getCipher(Key key, String algorithm, String mode, String padding, int encryptMode, byte[] iv,
                                   BouncyCastleProvider provider)
            throws Exception {
        Cipher cipher = Cipher.getInstance(StringUtils.join(new String[]{algorithm, mode, padding}, "/"), provider);
        if (mode.equals("ECB")) {
            cipher.init(encryptMode, key);
        } else if (mode.equals("CBC") && iv != null) {
            IvParameterSpec ivSpec = new IvParameterSpec(iv);
            cipher.init(encryptMode, key, ivSpec);
        }
        return cipher;
    }
    public static Object exec(Object... objects) throws Exception {
        if (objects == null || objects.length != 6) {
            return null;
        }
        byte[] message = (byte[]) objects[0];
        String mode = objects[1].toString();
        String padding = objects[2].toString();
        String passwordType = objects[3].toString();
        byte[] password = (byte[]) objects[4];
        byte[] iv = (byte[]) objects[5];
        Key key = SM4Demo.getKey(ALGORITHM, KEY_SIZE, passwordType, password);
        Cipher cipher = SM4Demo
                .getCipher(key, ALGORITHM, mode, padding, Cipher.ENCRYPT_MODE, iv, new BouncyCastleProvider());
        return cipher.doFinal(message);
    }

    public static Object dexec(Object... objects) throws Exception {
        if (objects == null || objects.length != 6) {
            return null;
        }
        byte[] message = (byte[]) objects[0];
        String mode = objects[1].toString();
        String padding = objects[2].toString();
        String passwordType = objects[3].toString();
        byte[] password = (byte[]) objects[4];
        byte[] iv = (byte[]) objects[5];
        Key key = SM4Demo.getKey(ALGORITHM, KEY_SIZE, passwordType, password);
        Cipher cipher = SM4Demo
                .getCipher(key, ALGORITHM, mode, padding, Cipher.DECRYPT_MODE, iv, new BouncyCastleProvider());
        return cipher.doFinal(message);
    }

//    public static void main(String[] args) throws Exception {
//        //待加密字符串
//        String content = "91320594067622605M";
//        SM4Demo computeFactor = new SM4Demo();
//        Object result = computeFactor
//                .exec(content.getBytes(), "ECB", "PKCS5Padding", "random", "ef5323158e0d43e69442718cd4932116".getBytes(),
//                        null);
//        System.out.println(Base64.getEncoder().encodeToString((byte[]) result));
//        //待解密的字符串
//        String encodeSM2String="t/lpTpuW6JeN+JhACXkWqWeHr55Bwj5BTBgMmG5a9+w=";
//        Object result2 = computeFactor.dexec(Base64.getDecoder().decode(encodeSM2String), "ECB", "PKCS5Padding", "random", "ef5323158e0d43e69442718cd4932116".getBytes(),null);
//        System.out.println(new String((byte[]) result2, Charset.forName("utf-8")));
//
//    }
}
