package cd.casic.module.machine.utils;

import cd.casic.module.machine.dal.model.Keypair;
import cn.hutool.log.Log;
import com.antherd.smcrypto.sm2.Sm2;
import com.antherd.smcrypto.sm3.Sm3;
import com.antherd.smcrypto.sm4.Sm4;
import com.antherd.smcrypto.sm4.Sm4Options;

import javax.script.ScriptException;

public class CryptogramUtil {

    private static final Log log = Log.get();

    /**
     * 加密方法（Sm2 的专门针对前后端分离，非对称秘钥对的方式，暴露出去的公钥，对传输过程中的密码加个密）
     *
     * @param str 待加密数据
     * @return 加密后的密文
     * @author yubaoshan
     */
    public static String doSm2Encrypt(String str) throws ScriptException {
        return Sm2.doEncrypt(str, Keypair.PUBLIC_KEY);
    }

    /**
     * 解密方法
     * 如果采用加密机的方法，用try catch 捕捉异常，返回原文值即可
     *
     * @param str 密文
     * @return 解密后的明文
     * @author yubaoshan
     */
    public static String doSm2Decrypt(String str) throws ScriptException {
        // 解密
        return Sm2.doDecrypt(str, Keypair.PRIVATE_KEY);
    }

    /**
     * 加密方法
     *
     * @param str 待加密数据
     * @return 加密后的密文
     * @author yubaoshan
     */
    public static String doEncrypt(String str) throws ScriptException {
        // SM4 加密  cbc模式
        Sm4Options sm4Options4 = new Sm4Options();
        sm4Options4.setMode("cbc");
        sm4Options4.setIv("fedcba98765432100123456789abcdef");
        return Sm4.encrypt(str, Keypair.KEY, sm4Options4);
    }

    /**
     * 解密方法
     * 如果采用加密机的方法，用try catch 捕捉异常，返回原文值即可
     *
     * @param str 密文
     * @return 解密后的明文
     * @author yubaoshan
     */
    public static String doDecrypt(String str) throws ScriptException {
        // 解密，cbc 模式，输出 utf8 字符串
        Sm4Options sm4Options8 = new Sm4Options();
        sm4Options8.setMode("cbc");
        sm4Options8.setIv("fedcba98765432100123456789abcdef");
        String docString = Sm4.decrypt(str, Keypair.KEY, sm4Options8);
        if (docString.isEmpty()) {
            log.warn(">>> 字段解密失败，返回原文值：{}", str);
            return str;
        } else {
            return docString;
        }
    }

    /**
     * 纯签名
     *
     * @param str 待签名数据
     * @return 签名结果
     * @author yubaoshan
     */
    public static String doSignature(String str) throws ScriptException {
        return Sm2.doSignature(str, Keypair.PRIVATE_KEY);
    }

    /**
     * 验证签名结果
     *
     * @param originalStr 签名原文数据
     * @param str         签名结果
     * @return 是否通过
     * @author yubaoshan
     */
    public static boolean doVerifySignature(String originalStr, String str) throws ScriptException {
        return Sm2.doVerifySignature(originalStr, str, Keypair.PUBLIC_KEY);
    }

    /**
     * 通过杂凑算法取得hash值，用于做数据完整性保护
     *
     * @param str 字符串
     * @return hash 值
     * @author yubaoshan
     */
    public static String doHashValue(String str) throws ScriptException {
        return Sm3.sm3(str);
    }

}
