package com.securitycontrol.common.security.utils;

import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

/**
 * @author HeiZi
 */
public class Sm3Utils {

    private static final String ENCODING = "UTF-8";

    /**
     * 不提供密钥
     * sm3算法加密
     * @param paramStr  待加密字符串
     * @return 返回加密后，固定长度=32的16进制字符串
     */
    public static String encrypt(String paramStr) {
        // 将返回的hash值转换成16进制字符串
        String resultHexString = "";
        try {
            // 将字符串转换成byte数组
            byte[] srcData = paramStr.getBytes(ENCODING);
            // 调用hash
            byte[] resultHash = hash(srcData);
            // 将返回的hash值转换成16进制字符串
            resultHexString = ByteUtils.toHexString(resultHash);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return resultHexString;
    }

    /**
     * 返回长度=32的byte数组
     * 生成对应的hash值
     * @param srcData
     * @return
     */
    public static byte[] hash(byte[] srcData) {
        //摘要加密
        SM3Digest digest = new SM3Digest();
        //使用指定的数组更新摘要
        digest.update(srcData,0,srcData.length);
        //获取摘要的长度
        byte[] hash = new byte[digest.getDigestSize()];
        digest.doFinal(hash,0);
        return hash;
    }

    /**
     * 通过密钥进行加密
     * 指定密钥进行加密
     * @param key 密钥
     * @param srcData 被加密的byte数组
     * @return
     */
    public static byte[] hmac(byte[] key,byte[] srcData) {
        KeyParameter keyParameter = new KeyParameter(key);
        SM3Digest digest = new SM3Digest();
        HMac mac = new HMac(digest);
        mac.init(keyParameter);
        mac.update(srcData,0,srcData.length);
        byte[] result = new byte[mac.getMacSize()];
        mac.doFinal(result,0);
        return result;
    }

    /**
     * 判断源数据与加密数据是否一致
     * 通过验证原数组和生成的hash数组是否为同一数组，验证两者是否为同意数据
     * @param srcStr 源字符串
     * @param sm3HexString 16进制字符串
     * @return 校验结构
     */
    public static boolean verify(String srcStr,String sm3HexString) {

        boolean flag = false;
        try {
            //原字符串
            byte[] srcData  = srcStr.getBytes(ENCODING);
            //16进制转为数组
            byte[] sm3Hash = ByteUtils.fromHexString(sm3HexString);
            //通过摘要加密生成新的hash数组
            byte[] newHash = hash(srcData);
            if (Arrays.equals(newHash,sm3Hash)) {
                flag = true;
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return flag;
    }

    public static void main(String[] args) {
        String str= encrypt("123456");
        String sm3="207cf410532f92a47dee245ce9b11ff71f578ebd763eb3bbea44ebd043d018fb";
        boolean  tf=str.equalsIgnoreCase(sm3);
        System.out.println(str);
        System.out.println(tf);
    }
}
