package com.inspect.base.core.utils;

import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.BCUtil;
import cn.hutool.crypto.ECKeyUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;

import java.util.HashMap;
import java.util.Map;

import org.bouncycastle.crypto.params.ECPrivateKeyParameters;

public class SmTools {
    public static void main(String[] args) {
        String publicKey = "049A91A9DD01B0505CC0F008228FDA15A6F226E4AAE089ACA5FEFE204F9184A70266E47548E8AB6F5FD8F6EA407C4E7869E4476CB1E1778DB5D37E99C45E67CA6C";
        String privateKey = "AD97C804E1F067261D552CD43E46B3C084496EBDB6AE53A58A17411E59A41597";
        String content = "1";
        System.out.println("私钥：" + privateKey);
        System.out.println("公钥：" + publicKey);
        String encryptData = sm2EncryptWithHex(content, publicKey);
        String decryptData = sm2DecryptWithHex(encryptData, privateKey);
        System.out.println("密文：" + encryptData);
        System.out.println("解密后明文：" + decryptData);
        sm2SignWithHex(content, privateKey);
        String signData = "6c74b9b8a3319d0373ea7e6d411b89c1e16d61ba762aede6442d6ce8c0540449c7a33403510de72a84b597b432771ba82aa8f3192f833e8d9baa5563fd0f510e";
        boolean bResult = sm2VerifySignWithHex(content, publicKey, signData);
        System.out.println("签名数据：" + signData);
        System.out.println("验证签名：" + bResult);
    }

    public static Map<String, byte[]> generateSm2KeyPair() {
        SM2 sm2 = SmUtil.sm2();
        Map<String, byte[]> byteKeyMap = new HashMap();
        byteKeyMap.put("privateKey", BCUtil.encodeECPrivateKey(sm2.getPrivateKey()));
        byteKeyMap.put("publicKey", BCUtil.encodeECPublicKey(sm2.getPublicKey(), false));
        return byteKeyMap;
    }

    public static Map<String, String> generateSm2KeyPairWithHex() {
        Map<String, byte[]> byteKeyMap = generateSm2KeyPair();
        Map<String, String> hexKeyMap = new HashMap<>();
        hexKeyMap.put("privateKey", HexUtil.encodeHexStr(byteKeyMap.get("privateKey")));
        hexKeyMap.put("publicKey", HexUtil.encodeHexStr(byteKeyMap.get("publicKey")));
        return hexKeyMap;
    }

    public static byte[] sm2Encrypt(byte[] data, byte[] publicKey) {
        SM2 sm2 = SmUtil.sm2((byte[]) null, publicKey);
        return sm2.encrypt(data, KeyType.PublicKey);
    }

    public static String sm2EncryptWithHex(String dataStr, String publicKeyHex) {
        byte[] result = sm2Encrypt(StrUtil.utf8Bytes(dataStr), HexUtil.decodeHex(publicKeyHex));
        return HexUtil.encodeHexStr(result);
    }

    public static byte[] sm2Dencrypt(byte[] data, byte[] privateKey) {
        SM2 sm2 = SmUtil.sm2(privateKey, (byte[]) null);
        return sm2.decrypt(data, KeyType.PrivateKey);
    }

    public static String sm2DecryptWithHex(String hexData, String privateKeyHex) {
        byte[] result = sm2Dencrypt(HexUtil.decodeHex(hexData), HexUtil.decodeHex(privateKeyHex));
        return StrUtil.utf8Str(result);
    }

    public static byte[] sm2Sign(byte[] data, byte[] privateKey) {
        SM2 sm2 = new SM2(privateKey, null, null);
        sm2.usePlainEncoding();
        return sm2.sign(data);
    }

    public static String sm2SignWithHex(String dataStr, String privateKeyHex) {
        byte[] result = sm2Sign(StrUtil.utf8Bytes(dataStr), HexUtil.decodeHex(privateKeyHex));
        return HexUtil.encodeHexStr(result);
    }

    public static boolean sm2VerifySign(byte[] data, byte[] publicKey, byte[] signData) {
        SM2 sm2 = new SM2(null, ECKeyUtil.toSm2PublicParams(publicKey));
        sm2.usePlainEncoding();
        return sm2.verify(data, signData);
    }

    public static boolean sm2VerifySignWithHex(String dataStr, String publicKeyHex, String signDataHex) {
        return sm2VerifySign(StrUtil.utf8Bytes(dataStr), HexUtil.decodeHex(publicKeyHex), HexUtil.decodeHex(signDataHex));
    }

    public static String sm3(String body) {
        return SmUtil.sm3(body);
    }
}
