package com.jiayue.ssi.util;

import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.BCUtil;
import cn.hutool.crypto.ECKeyUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import cn.hutool.crypto.SmUtil;
import com.jiayue.ssi.constant.SecretKeyConstants;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.signers.PlainDSAEncoding;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import java.util.HashMap;
import java.util.Map;

/**
 * sm2工具类
 *
 * @author xsl
 * @since 2023/02/28
 */
public class SM2CryptUtils {

    // 生成秘钥对
    public static Map<String, String> createSM2Key() {
        SM2 sm2 = SmUtil.sm2();
        sm2.setMode(SM2Engine.Mode.C1C3C2);
        // 这里会自动生成对应的随机秘钥对
        byte[] privateKey = BCUtil.encodeECPrivateKey(sm2.getPrivateKey());
        // 这里得到未压缩的公钥
        byte[] publicKey = ((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false);
        // 私钥
        String priKey = HexUtil.encodeHexStr(privateKey);
        // 公钥
        String pubKey = HexUtil.encodeHexStr(publicKey);
        Map<String, String> keys = new HashMap<>();
        keys.put(priKey, pubKey);
        return keys;
    }

    /**
     * 加密
     * @param data          数据
     * @param publicKey     公钥
     * @return
     */
    public static String encrypt(String data,String publicKey) {
        String publicKeyTmp = publicKey;
        if (publicKey.length() == 130) {
            // 这里需要去掉开始第一个字节 第一个字节表示标记
            publicKeyTmp = publicKey.substring(2);
        }
        String xhex = publicKeyTmp.substring(0, 64);
        String yhex = publicKeyTmp.substring(64, 128);
        ECPublicKeyParameters ecPublicKeyParameters = BCUtil.toSm2Params(xhex, yhex);
        // 创建sm2 对象
        SM2 sm2 = new SM2(null, ecPublicKeyParameters);
        sm2.usePlainEncoding();
        sm2.setMode(SM2Engine.Mode.C1C3C2);
        String hex = sm2.encryptHex(data, KeyType.PublicKey).substring(2);
        return hex;

    }

    /**
     * 解密
     * @param data          解密数据
     * @param privateKey    私钥
     * @return
     */
    public static String decrypt(String data,String privateKey) {
        SM2 sm2 = new SM2(ECKeyUtil.toSm2PrivateParams(privateKey), null);
        sm2.setMode(SM2Engine.Mode.C1C3C2);
        sm2.setEncoding(new PlainDSAEncoding());
        String encryptStr = sm2.decryptStr("04" + data, KeyType.PrivateKey);
        return encryptStr;
    }

    /**
     * 验证签名
     * @param publicKey     公钥
     * @param content       签名原内容
     * @param sign          签名
     * @return
     */
    public static boolean verifySign(String publicKey, String content, String sign) {
        SM2 sm2 = new SM2(null, publicKey);
        sm2.setMode(SM2Engine.Mode.C1C3C2);
        sm2.setEncoding(new PlainDSAEncoding());
        boolean verify = sm2.verifyHex(HexUtil.encodeHexStr(content), sign);
        return verify;
    }

    /**
     * 签名
     * @param privateKey    私钥
     * @param content       签名原内容
     * @return
     */
    public static String sign(String privateKey,String content) {
        SM2 sm2 = new SM2(privateKey, null);
        sm2.setEncoding(new PlainDSAEncoding());
        String sign = sm2.signHex(HexUtil.encodeHexStr(content));
        return sign;
    }

    public static void main(String[] args) {
//        String a = encrypt("ttttt", SecretKeyConstants.SERVER_PUBLIC_KEY);
//        System.out.println(a);
//        String b = decrypt(a, SecretKeyConstants.SERVER_PRIVATE_KEY);
//        System.out.println(b);

//        String base = "1276559e024c4f9b5c46f662ac51d69779bf4f9d278ef5215fbc36b5e4fc6da894545003694e4e71a01592edef940d6d13e88f8a09a9d91bdb214990b36ea34e";
//        System.out.println(verifySign(SecretKeyConstants.SERVER_PUBLIC_KEY,"测试",base));


//        String a = decrypt("ABC759C8C9FD55DFC92990580057A528073B0D498EFA0EDECE70DC55BF2DE0CCA1F5EC7E6F1FBD13586C3BA12F2A2795B82312A2FCFAA3A95323BAEE8690E4BD0E38F7C41024720098DFA16F2A7DCF27CD3C4750106A1C9B9A20FEA54E1C709D0AD2D3217152","E33C8730110B13828F2B04122831E62E71E4E990C7D277C4FA37EB68DCE25E33");
//        System.out.println(a);


        String a="Xsl147258";
        String b=SmUtil.sm3(a).toUpperCase();
        System.out.println(b);
        System.out.println(SM2CryptUtils.encrypt(b, SecretKeyConstants.SERVER_PUBLIC_KEY));
    }
}
