1 package com.foxinmy.weixin4j.util;
2
3 import java.util.Arrays;
4
5 import javax.crypto.Cipher;
6 import javax.crypto.spec.IvParameterSpec;
7 import javax.crypto.spec.SecretKeySpec;
8
9 import com.foxinmy.weixin4j.base64.Base64;
10
11
12
13
14
15
16
17
18
19
20 public final class MessageUtil {
21
22
23
24
25
26
27
28
29
30
31 public static String signature(String... para) {
32 Arrays.sort(para);
33 StringBuffer sb = new StringBuffer();
34 for (String str : para) {
35 sb.append(str);
36 }
37 return ServerToolkits.digestSHA1(sb.toString());
38 }
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public static String aesEncrypt(String appId, String encodingAesKey, String xmlContent) {
53
54
55
56
57
58
59 byte[] randomBytes = ServerToolkits.getBytesUtf8(ServerToolkits.generateRandomString(16));
60 byte[] xmlBytes = ServerToolkits.getBytesUtf8(xmlContent);
61 int xmlLength = xmlBytes.length;
62 byte[] orderBytes = new byte[4];
63 orderBytes[3] = (byte) (xmlLength & 0xFF);
64 orderBytes[2] = (byte) (xmlLength >> 8 & 0xFF);
65 orderBytes[1] = (byte) (xmlLength >> 16 & 0xFF);
66 orderBytes[0] = (byte) (xmlLength >> 24 & 0xFF);
67 byte[] appidBytes = ServerToolkits.getBytesUtf8(appId);
68
69 int byteLength = randomBytes.length + xmlLength + orderBytes.length + appidBytes.length;
70
71 byte[] padBytes = PKCS7Encoder.encode(byteLength);
72
73 byte[] unencrypted = new byte[byteLength + padBytes.length];
74 byteLength = 0;
75
76 System.arraycopy(randomBytes, 0, unencrypted, byteLength, randomBytes.length);
77 byteLength += randomBytes.length;
78 System.arraycopy(orderBytes, 0, unencrypted, byteLength, orderBytes.length);
79 byteLength += orderBytes.length;
80 System.arraycopy(xmlBytes, 0, unencrypted, byteLength, xmlBytes.length);
81 byteLength += xmlBytes.length;
82 System.arraycopy(appidBytes, 0, unencrypted, byteLength, appidBytes.length);
83 byteLength += appidBytes.length;
84 System.arraycopy(padBytes, 0, unencrypted, byteLength, padBytes.length);
85 try {
86 byte[] aesKey = Base64.decodeBase64(encodingAesKey + "=");
87
88 Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
89 SecretKeySpec keySpec = new SecretKeySpec(aesKey, ServerToolkits.AES);
90 IvParameterSpec iv = new IvParameterSpec(aesKey, 0, 16);
91 cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
92
93 byte[] encrypted = cipher.doFinal(unencrypted);
94
95
96 return Base64.encodeBase64String(encrypted);
97 } catch (Exception e) {
98 throw new RuntimeException("-40006,AES加密失败:" + e.getMessage());
99 }
100 }
101
102
103
104
105
106
107
108
109
110
111
112
113 public static String aesDecrypt(String appId, String encodingAesKey, String encryptContent) {
114 byte[] aesKey = Base64.decodeBase64(encodingAesKey + "=");
115 byte[] original;
116 try {
117
118 Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
119 SecretKeySpec key_spec = new SecretKeySpec(aesKey, ServerToolkits.AES);
120 IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16));
121 cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);
122
123 byte[] encrypted = Base64.decodeBase64(encryptContent);
124
125 original = cipher.doFinal(encrypted);
126 } catch (Exception e) {
127 throw new RuntimeException("-40007,AES解密失败:" + e.getMessage());
128 }
129 String xmlContent, fromAppId;
130 try {
131
132 byte[] bytes = PKCS7Encoder.decode(original);
133
134
135
136
137
138 byte[] lengthByte = Arrays.copyOfRange(bytes, 16, 20);
139
140
141 int xmlLength = lengthByte[3] & 0xff | (lengthByte[2] & 0xff) << 8 | (lengthByte[1] & 0xff) << 16
142 | (lengthByte[0] & 0xff) << 24;
143 xmlContent = ServerToolkits.newStringUtf8(Arrays.copyOfRange(bytes, 20, 20 + xmlLength));
144 fromAppId = ServerToolkits.newStringUtf8(Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length));
145 } catch (Exception e) {
146 throw new RuntimeException("-40008,xml内容不合法:" + e.getMessage());
147 }
148
149 if (appId != null && !fromAppId.trim().equals(appId)) {
150 throw new RuntimeException("-40005,校验AppID失败,expect " + appId + ",but actual is " + fromAppId);
151 }
152 return xmlContent;
153 }
154 }