xuhy
6 天以前 07d0d74e8db1d9e536fdfe33b80c568ccfc7febe
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
package com.ruoyi.jianguan.util;
 
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));
    }
}