package com.ruoyi.integration.drainage; import com.alibaba.fastjson.JSONObject; import org.apache.commons.lang3.StringUtils; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; /** * 签名工具 * @author zhibing.pu * @Date 2025/1/23 11:30 */ public class SignUtil { /*************************************快电******************************************/ /** * 签名算法 * * @param aValue 加密的原文,即源数据 * @param aKey 密钥 这是针对一条字符串进行加密的方法 */ public static String hmacSign (String aValue, String aKey) { byte k_ipad[] = new byte[64]; byte k_opad[] = new byte[64]; byte keyb[]; byte value[]; try { keyb = aKey.getBytes("UTF-8"); value = aValue.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { keyb = aKey.getBytes(); value = aValue.getBytes(); } Arrays.fill(k_ipad, keyb.length, 64, (byte) 54); Arrays.fill(k_opad, keyb.length, 64, (byte) 92); for (int i = 0; i < keyb.length; i++) { k_ipad[i] = (byte) (keyb[i] ^ 0x36); k_opad[i] = (byte) (keyb[i] ^ 0x5c); } MessageDigest md = null; try { md = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { return null; } md.update(k_ipad); md.update(value); byte dg[] = md.digest(); md.reset(); md.update(k_opad); md.update(dg, 0, 16); dg = md.digest(); return toHex(dg); } public static String toHex (byte input[]) { if (input == null) { return null; } StringBuffer output = new StringBuffer(input.length * 2); for (int i = 0; i < input.length; i++) { int current = input[i] & 0xff; if (current < 16) { output.append("0"); } output.append(Integer.toString(current, 16)); } return output.toString().toUpperCase(); } /*************************************新电途******************************************/ /** * 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组成的字符串; * ⊕表示异或运算; * ∣表示连接操作。 **/ public 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 < length; 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转化为字符串 **/ public 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(); } public static void main(String[] args) { // String encrypt = AESUtil.encrypt("{\"total\":1,\"stationStatusInfo\":{\"operationID\":\"123456789\",\"stationID\":\"111111111111111\",\"connectorStatusInfos\":{\"connectorID\":1,\"equipmentID\":\"10000000000000000000001\",\"status\":4,\"currentA\":0,\"currentB\":0,\"currentC\":0,\"voltageA\":0,\"voltageB\":0,\"voltageC\":0,\"soc\":10,}}}"); // String s = hmacSign(encrypt, "123456789abcdef"); // System.err.println(s); //签名秘钥SigSecret String key = "1234567890abcdef"; //运营商标识OperatorId String operatorId = "123456789"; //参数信息Data String data = "il7B0BSEjFdzpyKzfOFpvg/Se1CP802RItKYFPfSLRxJ3jf0bVl9hvYOEktPAYW2nd7S8MBcyHYyacHKbISq5iTmDzG+ivnR+SZJv3USNTYVMz9rCQVSxd0cLlqsJauko79NnwQJbzDTyLooYoIwz75qBOH2/xOMirpeEqRJrF/EQjWekJmGk9RtboXePu2rka+Xm51syBPhiXJAq0GfbfaFu9tNqs/e2Vjja/ltE1M0lqvxfXQ6da6HrThsm5id4ClZFIi0acRfrsPLRixS/IQYtksxghvJwbqOsbIsITail9Ayy4tKcogeEZiOO+4Ed264NSKmk7l3wKwJLAFjCFogBx8GE3OBz4pqcAn/ydA="; //时间戳TimeStamp(格式:年月日时分秒) String timeStamp = "20160729142400"; //自增序列Seq String seq = "0001"; //进行字符串拼接、计算 String m = new StringBuilder(operatorId).append(data).append(timeStamp).append(seq).toString(); byte[] hmacMd5 = getHMacMD5Bytes(key.getBytes(), m.getBytes()); // 打印计算得到的签名Sig System.out.println(bytesToHexString(hmacMd5)); } }