package cd.casic.framework.commons.util.encrypt;

import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PKCS7Padding;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Arrays;
import java.util.Base64;

/**
 * @author by mianbin
 * @Classname AESUtil
 * @Description 加密算法，后面加GM算法
 * @Date 2025/3/18 11:15
 */
public class AESUtil {
    private static final String AES = "AES";
    private static final Integer SEED = 256;

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

    public static String decrypt(String key, String content) {
        byte[] bytes = Base64.getDecoder().decode(content);
        KeyParameter keyParameter = generateKeyParameter(key);
        byte[] output = processData(false, keyParameter, bytes);
        return Base64.getEncoder().encodeToString(output);
    }

    public static byte[] decrypt(String key, byte[] content) {
        KeyParameter keyParameter = generateKeyParameter(key);
        return processData(false, keyParameter, content);
    }

    public static String encrypt(String key, String content) {
        byte[] bytes = content.getBytes(StandardCharsets.UTF_8);
        KeyParameter keyParameter = generateKeyParameter(key);
        byte[] output = processData(true, keyParameter, bytes);
        return Base64.getEncoder().encodeToString(output);
    }

    public static byte[] encrypt(String key, byte[] content) {
        KeyParameter keyParameter = generateKeyParameter(key);
        return processData(true, keyParameter, content);
    }

    private static byte[] processData(boolean encrypt, KeyParameter keyParameter, byte[] bytes) {
        PKCS7Padding blockCipherPadding = new PKCS7Padding();
        CBCBlockCipher blockCipher = new CBCBlockCipher(new AESEngine());
        PaddedBufferedBlockCipher paddedBufferedBlockCipher = new PaddedBufferedBlockCipher(blockCipher, blockCipherPadding);
        paddedBufferedBlockCipher.init(encrypt, keyParameter);

        byte[] output = new byte[paddedBufferedBlockCipher.getOutputSize(bytes.length)];
        int offset = paddedBufferedBlockCipher.processBytes(bytes, 0, bytes.length, output, 0);
        int outputLength = 0;
        try {
            outputLength = paddedBufferedBlockCipher.doFinal(output, offset);
        } catch (InvalidCipherTextException e) {
            e.printStackTrace();
        }
        return Arrays.copyOf(output, offset + outputLength);
    }

    private static KeyParameter generateKeyParameter(String key) {
        KeyGenerator keyGenerator = null;
        SecureRandom secureRandom = null;
        try {
            keyGenerator = KeyGenerator.getInstance(AES);
            secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.setSeed(key.getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            e.printStackTrace();
        }

        keyGenerator.init(SEED, secureRandom);
        SecretKey secretKey = keyGenerator.generateKey();
        byte[] encoded = secretKey.getEncoded();
        return new KeyParameter(encoded);
    }
}
