中电联协议HMAC-MD5签名算法实现

HMAC(K,M)=H(K⊕opad∣H(K⊕ipad∣M))

package com.aesiny.utils;

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

/**
 * @Description
 * @ClassName HMacMD5Util
 * @Author Aesiny.L
 * @Date 2020-1-10 14:23
 **/
public class HMacMD5Util {

    public static void main(String[] args){
        String key = "1234567890abcdef";
        String operatorId = "123456789";
        String data = "il7B0BSEjFdzpyKzfOFpvg/Se1CP802RItKYFPfSLRxJ3jf0bVl9hvYOEktPAYW2nd7S8MBcyHYyacHKbISq5iTmDzG+ivnR+SZJv3USNTYVMz9rCQVSxd0cLlqsJauko79NnwQJbzDTyLooYoIwz75qBOH2/xOMirpeEqRJrF/EQjWekJmGk9RtboXePu2rka+Xm51syBPhiXJAq0GfbfaFu9tNqs/e2Vjja/ltE1M0lqvxfXQ6da6HrThsm5id4ClZFIi0acRfrsPLRixS/IQYtksxghvJwbqOsbIsITail9Ayy4tKcogeEZiOO+4Ed264NSKmk7l3wKwJLAFjCFogBx8GE3OBz4pqcAn/ydA=";
        String timeStamp = "20160729142400";
        String seq = "0001";
        String m = new StringBuilder(operatorId).append(data).append(timeStamp).append(seq).toString();
        byte[] macMD5 = HMacMD5Util.getHMacMD5Bytes(key.getBytes(), m.getBytes());
        System.out.println(HMacMD5Util.bytesToHexString(macMD5));
    }

    /**
     * HmacMd5的计算公式为:HMAC(K,M) = H(K⊕opad∣H(K⊕ipad∣M))
     * 其中:K是密钥(byte[] key),长度可为64字节(后面涉及描述都是以字节byte进行),若小于该长度,在密钥后面用0(即0x00)补齐。
     * M是消息内容(byte[] m);
     * H是散列函数(此处采用MD5);
     * opad和ipad分别是由若干个0x5c和0x36组成的字符串;
     * ⊕表示异或运算;
     * ∣表示连接操作。
     **/
    private static byte[] getHMacMD5Bytes(byte[] key, byte[] m) {
        try {
            //定义长度
            int length = 64;
            //定义opad和ipad
            byte[] opad = new byte[length];
            byte[] ipad = new byte[length];
            for (int i = 0; i < 64; i++) {
                opad[i] = 0x5C;
                ipad[i] = 0x36;
            }
            byte[] actualKey = key;
            byte[] keyArr = new byte[length];
            //如果密钥长度,大于64字节,就使用MD5算法计算其散列值,作为密钥
            if (key.length > length) {
                actualKey = md5(key);
            }
            for (int i = 0; i < actualKey.length; i++) {
                keyArr[i] = actualKey[i];
            }
            //如果密钥长度不足64字节,就使用0x00补齐到64字节
            if (actualKey.length < length) {
                for (int i = key.length; i < length; i++)
                    keyArr[i] = 0x00;
            }
            //使用密钥和ipad进行异或运算【K⊕ipad】
            byte[] kIpadXorResult = new byte[length];
            for (int i = 0; i < length; i++) {
                kIpadXorResult[i] = (byte) (keyArr[i] ^ ipad[i]);
            }
            //将待加密数据M追加到kIpadXorResult后面【K⊕ipad∣M】
            byte[] firstAppendResult = new byte[kIpadXorResult.length + m.length];
            for (int i = 0; i < kIpadXorResult.length; i++) {
                firstAppendResult[i] = kIpadXorResult[i];
            }
            for (int i = 0; i < m.length; i++) {
                firstAppendResult[i + keyArr.length] = m[i];
            }
            //做MD5运算【H(K⊕ipad∣M)】
            byte[] firstHashResult = md5(firstAppendResult);

            //使用密钥和opad进行异或运算【K⊕opad】
            byte[] kOpadXorResult = new byte[length];
            for (int i = 0; i < length; i++) {
                kOpadXorResult[i] = (byte) (keyArr[i] ^ opad[i]);
            }
            //将firstHashResult追加到kOpadXorResult后面【K⊕opad∣H(K⊕ipad∣M)】
            byte[] secondAppendResult = new byte[kOpadXorResult.length + firstHashResult.length];
            for (int i = 0; i < kOpadXorResult.length; i++) {
                secondAppendResult[i] = kOpadXorResult[i];
            }
            for (int i = 0; i < firstHashResult.length; i++) {
                secondAppendResult[kOpadXorResult.length + i] = firstHashResult[i];
            }
            //做MD5运算【H(K⊕opad∣H(K⊕ipad∣M))】
            return md5(secondAppendResult);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * MD5(产生出一个128位(16字节)的散列值)
     **/
    private static byte[] md5(byte[] str) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(str);
        return md.digest();
    }

    /**
     * HEX转化为字符串
     **/
    private static String bytesToHexString(byte[] m) {
        StringBuilder stringBuilder = new StringBuilder();
        if (m == null || m.length <= 0) {
            return null;
        }
        for (int i = 0; i < m.length; i++) {
            int v = m[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString().toUpperCase();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值