1 package com.zone.weixin4j.util;
2
3 import com.zone.weixin4j.base64.Base64;
4 import com.zone.weixin4j.exception.WeixinException;
5
6 import javax.crypto.Cipher;
7 import javax.crypto.spec.IvParameterSpec;
8 import javax.crypto.spec.SecretKeySpec;
9 import java.util.Arrays;
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,
53 String xmlContent) throws WeixinException {
54
55
56
57
58
59
60 byte[] randomBytes = ServerToolkits.getBytesUtf8(ServerToolkits
61 .generateRandomString(16));
62 byte[] xmlBytes = ServerToolkits.getBytesUtf8(xmlContent);
63 int xmlLength = xmlBytes.length;
64 byte[] orderBytes = new byte[4];
65 orderBytes[3] = (byte) (xmlLength & 0xFF);
66 orderBytes[2] = (byte) (xmlLength >> 8 & 0xFF);
67 orderBytes[1] = (byte) (xmlLength >> 16 & 0xFF);
68 orderBytes[0] = (byte) (xmlLength >> 24 & 0xFF);
69 byte[] appidBytes = ServerToolkits.getBytesUtf8(appId);
70
71 int byteLength = randomBytes.length + xmlLength + orderBytes.length
72 + appidBytes.length;
73
74 byte[] padBytes = PKCS7Encoder.encode(byteLength);
75
76 byte[] unencrypted = new byte[byteLength + padBytes.length];
77 byteLength = 0;
78
79 System.arraycopy(randomBytes, 0, unencrypted, byteLength,
80 randomBytes.length);
81 byteLength += randomBytes.length;
82 System.arraycopy(orderBytes, 0, unencrypted, byteLength,
83 orderBytes.length);
84 byteLength += orderBytes.length;
85 System.arraycopy(xmlBytes, 0, unencrypted, byteLength, xmlBytes.length);
86 byteLength += xmlBytes.length;
87 System.arraycopy(appidBytes, 0, unencrypted, byteLength,
88 appidBytes.length);
89 byteLength += appidBytes.length;
90 System.arraycopy(padBytes, 0, unencrypted, byteLength, padBytes.length);
91 try {
92 byte[] aesKey = Base64.decodeBase64(encodingAesKey + "=");
93
94 Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
95 SecretKeySpec keySpec = new SecretKeySpec(aesKey, ServerToolkits.AES);
96 IvParameterSpec iv = new IvParameterSpec(aesKey, 0, 16);
97 cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
98
99 byte[] encrypted = cipher.doFinal(unencrypted);
100
101
102 return Base64
103 .encodeBase64String(encrypted);
104 } catch (Exception e) {
105 throw new WeixinException("-40006", "AES加密失败:" + e.getMessage());
106 }
107 }
108
109
110
111
112
113
114
115
116
117
118
119
120 public static String aesDecrypt(String appId, String encodingAesKey,
121 String encryptContent) throws WeixinException {
122 byte[] aesKey = Base64.decodeBase64(encodingAesKey + "=");
123 byte[] original;
124 try {
125
126 Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
127 SecretKeySpec key_spec = new SecretKeySpec(aesKey, ServerToolkits.AES);
128 IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey,
129 0, 16));
130 cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);
131
132 byte[] encrypted = Base64.decodeBase64(encryptContent);
133
134 original = cipher.doFinal(encrypted);
135 } catch (Exception e) {
136 throw new WeixinException("-40007", "AES解密失败:" + e.getMessage());
137 }
138 String xmlContent, fromAppId;
139 try {
140
141 byte[] bytes = PKCS7Encoder.decode(original);
142
143
144
145
146
147 byte[] lengthByte = Arrays.copyOfRange(bytes, 16, 20);
148
149
150 int xmlLength = lengthByte[3] & 0xff | (lengthByte[2] & 0xff) << 8
151 | (lengthByte[1] & 0xff) << 16
152 | (lengthByte[0] & 0xff) << 24;
153 xmlContent = ServerToolkits.newStringUtf8(Arrays.copyOfRange(bytes, 20,
154 20 + xmlLength));
155 fromAppId = ServerToolkits.newStringUtf8(Arrays.copyOfRange(bytes,
156 20 + xmlLength, bytes.length));
157 } catch (Exception e) {
158 throw new WeixinException("-40008", "xml内容不合法:" + e.getMessage());
159 }
160
161 if (appId != null && !fromAppId.trim().equals(appId)) {
162 throw new WeixinException("-40005", "校验AppID失败,expect " + appId
163 + ",but actual is " + fromAppId);
164 }
165 return xmlContent;
166 }
167 }