package com.ruoyi.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.quick.api.grpc.v1.MacAlg;
import org.quick.api.grpc.v1.SymAlg;
import org.quick.api.grpc.v1.SymAlgPaddingMode;
import org.quickssl.api.CryptoClient;
import org.quickssl.api.CryptoHelper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
 * 加解密工具
 */
@Slf4j
@Component
public class EncryptDecryptUtil {

    /**
     * socket ip:port
     */
    @Value(value = "${cipher-security.socket}")
    private String socket;
    /**
     * path  证书绝对路径
     */
    @Value(value = "${cipher-security.path}")
    private String path;

    /**
     * 密钥标识
     */
    private static final String CIPHER_IDENTIFICATION = "default";
    /**
     * IV
     */
    private static final String IV = "1234567812345678";


    // 初始化加密配置
    @PostConstruct
    public void init() {
        try {
            String pem = path + File.separator + "cacert.pem";
            String pfx = path + File.separator + "client.pfx";
            CryptoClient.Config config = CryptoClient.Config.newBuilder()
                    .setSocket(socket)
                    .setCaCertFile(pem)
                    .setKeyStoreFile(pfx)
                    .build();
            CryptoHelper.initConfig(config);
        } catch (CryptoClient.CryptoException e) {
            log.error("奇安信国密安全密码应用中间件初始化失败：", e);
            throw new RuntimeException(e);
        }
    }


    /**
     * sm4加密
     *
     * @param originData 源数据
     * @return 密文数据
     */
    public String sm4Encrypt(String originData) throws CryptoClient.CryptoException {
        return sm4Encrypt(CIPHER_IDENTIFICATION, originData);
    }

    /**
     * sm4加密
     *
     * @param cipherIdentification 密钥标识
     * @param originData           源数据
     * @return 密文数据
     */
    public String sm4Encrypt(String cipherIdentification, String originData)
            throws CryptoClient.CryptoException {
        byte[] cipher = CryptoHelper.symmEncrypt(cipherIdentification, SymAlg.QK_SGD_SM4_CBC,
                SymAlgPaddingMode.QK_SYMALG_PADDING_PKCS7, IV.getBytes(StandardCharsets.UTF_8),
                originData.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(cipher);
    }

    /**
     * sm4解密
     *
     * @param cipherData 密文数据
     * @return 源数据
     */
    public String sm4Decrypt(String cipherData) throws CryptoClient.CryptoException {
        return sm4Decrypt(CIPHER_IDENTIFICATION, cipherData);
    }

    /**
     * sm4解密
     *
     * @param cipherIdentification 密钥标识
     * @param cipherData           密文数据
     * @return 源数据
     */
    public String sm4Decrypt(String cipherIdentification, String cipherData)
            throws CryptoClient.CryptoException {
        byte[] origin = CryptoHelper.symmDecrypt(cipherIdentification, SymAlg.QK_SGD_SM4_CBC,
                SymAlgPaddingMode.QK_SYMALG_PADDING_PKCS7, IV.getBytes(StandardCharsets.UTF_8),
                Base64.getDecoder().decode(cipherData));
        return new String(origin);
    }

    /**
     * sm3杂凑
     *
     * @param originData 源数据
     */
    public String sm3Hash(String originData) throws CryptoClient.CryptoException {
        return sm3Hash(CIPHER_IDENTIFICATION, originData);
    }

    /**
     * sm3杂凑
     *
     * @param cipherIdentification 密钥标识
     * @param originData           源数据
     * @return 杂凑数据
     */
    public String sm3Hash(String cipherIdentification, String originData)
            throws CryptoClient.CryptoException {
        byte[] hash = CryptoHelper.calculateMAC(cipherIdentification, MacAlg.QK_HMAC_SM3,
                originData.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(hash);
    }

    /**
     * sm3验证
     *
     * @param originData 源数据
     * @param hashData   杂凑数据
     * @return 验证结果
     */
    public boolean sm3Verify(String originData, String hashData) throws CryptoClient.CryptoException {
        return sm3Verify(CIPHER_IDENTIFICATION, originData, hashData);
    }

    /**
     * sm3验证
     *
     * @param cipherIdentification 密钥标识
     * @param originData           源数据
     * @param hashData             杂凑数据
     * @return 验证结果
     */
    public boolean sm3Verify(String cipherIdentification, String originData, String hashData)
            throws CryptoClient.CryptoException {
        return CryptoHelper.verifyMAC(cipherIdentification, MacAlg.QK_HMAC_SM3,
                originData.getBytes(StandardCharsets.UTF_8), Base64.getDecoder().decode(hashData));
    }

}
