package com.jsowell.thirdparty.nanrui.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * TODO
 *
 * @author Lemon
 * @Date 2023/10/12 13:42
 */
public class NRMD5Util {
    public static void main(String[] args) {
        String sigSecret = "yyyyyyyyyyyyyyyy";
        String dataSecret = "DDDDDDD";
        String dataSecretIv = "XXXXXXXX";
        String operatorId = "MA002TMQX";
        String data = "{'EquipAuthSeq':'MA002TMQX202004090925368255','ConnectorID':'MA01H3BQ1_1306060015204'}";
        String retData = QEncodeUtil.encrypt(data, dataSecret, dataSecretIv);
        String timeStamp = "20200409000000";
        String seq = "0001";
        String sig = getHmacMd5Str(sigSecret, operatorId + retData + timeStamp + seq);
    }

    public static String getHmacMd5Str(String key, String data) {
        String result = "";
        try {
            byte[] keyByte = key.getBytes("UTF-8");
            byte[] dataByte = data.getBytes("UTF-8");
            byte[] hmacMd5Byte = getHmacMd5Bytes(keyByte, dataByte);
            StringBuffer md5StrBuff = new StringBuffer();
            for (byte b : hmacMd5Byte) {
                if (Integer.toHexString(0xFF & b).length() == 1)
                    md5StrBuff.append("0").append(Integer.toHexString(0xFF & b));
                else md5StrBuff.append(Integer.toHexString(0xFF & b));
            }
            result = md5StrBuff.toString().toUpperCase();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public static byte[] getHmacMd5Bytes(byte[] key, byte[] data) throws NoSuchAlgorithmException {
        /**
         * HmacMd5 calculation formula: H(K XOR opad, H(K XOR ipad, text))
         * HmacMd5 计算公式：H(K XOR opad, H(K XOR ipad, text))
         * H 代表 hash 算法，本类中使用 MD5 算法，K 代表密钥，text 代表要加密的数据 ipad 为 0x36，opad 为 0x5C。
         */
        int length = 64;
        byte[] ipad = new byte[length];
        byte[] opad = new byte[length];
        for (int i = 0; i < 64; i++) {
            ipad[i] = 0x36;
            opad[i] = 0x5C;
        }
        byte[] actualKey = key;
        // Actual key.
        byte[] keyArr = new byte[length];
        // 如果密钥长度，大于 64 字节，就使用哈希算法，计算其摘要，作为真正的密钥。
        if (key.length > length) {
            actualKey = md5(key);
        }
        // append zeros to K 如果密钥长度不足 64 字节，就使用 0x00 补齐到 64 字节。
        System.arraycopy(actualKey, 0, keyArr, 0, actualKey.length);
        if (actualKey.length < length) {
            for (int i = actualKey.length; i < keyArr.length; i++) keyArr[i] = 0x00;
        }
        // calc K XOR ipad 使用密钥和 ipad 进行异或运算。
        byte[] kIpadXorResult = new byte[length];
        for (int i = 0; i < length; i++) {
            kIpadXorResult[i] = (byte) (keyArr[i] ^ ipad[i]);
        }
        // append "text" to the end of "K XOR ipad" 将待加密数据追加到 K XOR ipad 计算结果后面。
        byte[] firstAppendResult = new byte[kIpadXorResult.length + data.length];
        System.arraycopy(kIpadXorResult, 0, firstAppendResult, 0, kIpadXorResult.length);
        // calc H(K XOR ipad, text) 使用哈希算法计算上面结果的摘要
        System.arraycopy(data, 0, firstAppendResult, keyArr.length, data.length);
        // calc K XOR opad 使用密钥和 opad 进行异或运算。
        byte[] firstHashResult = md5(firstAppendResult);
        byte[] kOpadXorResult = new byte[length];
        for (int i = 0; i < length; i++) {
            kOpadXorResult[i] = (byte) (keyArr[i] ^ opad[i]);
        }
        // 将 H(K XOR  * ipad, text)结果追加到 K XOR opad 结果后面
        byte[] secondAppendResult = new byte[kOpadXorResult.length + firstHashResult.length]; //
        System.arraycopy(kOpadXorResult, 0, secondAppendResult, 0, kOpadXorResult.length);
        // 对上面的数据进行哈希运算。
        System.arraycopy(firstHashResult, 0, secondAppendResult, keyArr.length, firstHashResult.length);
        return md5(secondAppendResult);
    }

    private static byte[] md5(byte[] str) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(str);
        return md.digest();
    }
}
