String decrypt(String text) {
byte[] original;
try {
// 设置解密模式为AES的CBC模式
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec key_spec = new SecretKeySpec(aesKey, "AES");
IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16));
cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);
// 使用BASE64对密文进行解码
byte[] encrypted = Base64.decodeBase64(text);
// 解密
original = cipher.doFinal(encrypted);
} catch (Exception e) {
e.printStackTrace();
throw new AesException(AesException.DecryptAESError);
}
String xmlContent, from_id;
try {
// 去除补位字符
byte[] bytes = PKCS7Encoder.decode(original);
// 分离16位随机字符串,网络字节序和AppId
byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20);
int xmlLength = recoverNetworkBytesOrder(networkOrder);
System.out.println("xmlLength = " + xmlLength);
xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), CHARSET);
from_id = new String(Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length),
CHARSET);
} catch (Exception e) {
e.printStackTrace();
throw new AesException(AesException.IllegalBuffer);
}
// appid不相同的情况
if (StringUtils.isBlank(appid) && !from_id.equals(receiveid)) {
throw new AesException(AesException.ValidateAppidError);
}
return xmlContent;
}
说明:企业微信消息回调解密正常,xmlLength 二三百;公众号消息解密时,xmlLength 是一个正负十位整数。创建URL时,企业微信需要解密echostr并返回解密后的字符串,而微信公众号直接返回无需解密,是否不是一个解密体系?为什么企业微信公众平台——公众号的上文档中的解密SDK,企业微信消息可以使用,公众号却使用不了,企业项目比较急!急需要解决!
日志:
2022-03-15 11:07:56.762 INFO 11212 --- [nio-8001-exec-1] c.g.wx.cp.controller.WXKeFuController : 接收到回调:keFuId 1001, msg_signature e6e1869e1f94cf73f140ba0c96719956eddaf762, timestamp 1647313676, nonce 699393265
sPostData = <xml>
<ToUserName><![CDATA[gh_251e2d32914a]]></ToUserName>
<Encrypt><![CDATA[DF8rpixK6xQaLGPCM2QECCmQ1aNVCeDDr4ByF1r4ZoINJWpYwtBp8KMHCplPFTvf3Cv/wKjsCEDUxoZQpQyntIZIExeEr7glp4N+4+v+wCkWd0Kodm2cBkXPV6wXwW8aaiwWAIkqPKMU+ki5u+xqySVHAwhUg4KnQOw5XGhbrGC5JDCCPd6XtHT48aQ0xFdkzHoeVgyDDnqp4e4d4zPDVx6UIyTOh3tXd6NvAHIOEG1Gn2g8trZvrs88bBCXjtS2tY/1+ETGTZI7Bj+iu2m/l/eGyvQmEMAJlV6D2GZL/uPFXvrzdm2ThSZfz5epPcjWu6NbxyyFrT0UKMHkEmNccWxvGiasLG7/T6gGiqJzyhQN48NcN33Q2wp9q6WUARkUacC3sFNwI1dPQsaXjmmXgO/hDJrJVotkSv1D5sP+J0c=]]></Encrypt>
</xml>
encrypt = DF8rpixK6xQaLGPCM2QECCmQ1aNVCeDDr4ByF1r4ZoINJWpYwtBp8KMHCplPFTvf3Cv/wKjsCEDUxoZQpQyntIZIExeEr7glp4N+4+v+wCkWd0Kodm2cBkXPV6wXwW8aaiwWAIkqPKMU+ki5u+xqySVHAwhUg4KnQOw5XGhbrGC5JDCCPd6XtHT48aQ0xFdkzHoeVgyDDnqp4e4d4zPDVx6UIyTOh3tXd6NvAHIOEG1Gn2g8trZvrs88bBCXjtS2tY/1+ETGTZI7Bj+iu2m/l/eGyvQmEMAJlV6D2GZL/uPFXvrzdm2ThSZfz5epPcjWu6NbxyyFrT0UKMHkEmNccWxvGiasLG7/T6gGiqJzyhQN48NcN33Q2wp9q6WUARkUacC3sFNwI1dPQsaXjmmXgO/hDJrJVotkSv1D5sP+J0c=
appid = wxde9c540c3328dbcc
第三方收到URL中的签名:e6e1869e1f94cf73f140ba0c96719956eddaf762
第三方校验签名:e6e1869e1f94cf73f140ba0c96719956eddaf762
xmlLength = -566866243
java.lang.IllegalArgumentException: 20 > -566866223
at java.util.Arrays.copyOfRange(Arrays.java:3519)
at com.gyhn.wx.cp.model.qywx.WXBizMsgCrypt.decrypt(WXBizMsgCrypt.java:281)
at com.gyhn.wx.cp.model.qywx.WXBizMsgCrypt.decryptMsg(WXBizMsgCrypt.java:365)
...........................
2022-03-15 11:07:56.799 ERROR 11212 --- [nio-8001-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.gyhn.wx.cp.model.AesException: 解密后得到的buffer非法] with root cause
com.gyhn.wx.cp.model.AesException: 解密后得到的buffer非法
at com.gyhn.wx.cp.model.qywx.WXBizMsgCrypt.decrypt(WXBizMsgCrypt.java:286) ~[classes/:na]
at com.gyhn.wx.cp.model.qywx.WXBizMsgCrypt.decryptMsg(WXBizMsgCrypt.java:365) ~[classes/:na]
...........................
出错代码
int xmlLength = recoverNetworkBytesOrder(networkOrder);
xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), CHARSET);
老哥解决了没有
int xmlLength = recoverNetworkBytesOrder(networkOrder); 官方给提供的代码,这行妥妥的有bug吧? 1、密文是企微通知的 2、签名校验通过 3、执行这行代码的时候,从日志里抓了个报错的参数。debug出来,计算出来居然有19亿的长度。 4、copyOfRange 执行这个方法的时候里面new byte[19亿] copyOfRange 方法里,有判断 to 必须 大于 from,xmlLength 计算出来个19亿,这是稳稳的会报异常啊。显然不满足jdk方法copyOfRange里的 to 大于 from的条件
所以,网络协议指定了通讯字节序:大端。只有在多字节数据处理时才需要考虑字节序,运行在同一台计算机上的进程相互通信时,一般不用考虑字节序,异构计算机之间通讯,需要转换自己的字节序为网络字节。主机字节序是小端,所以才需要进行字节序转换。
————————————————
版权声明:本文为CSDN博主「~青萍之末~」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/daaikuaichuan/article/details/83061117
你好,解决了吗?有碰到替换jar也没有效果
您好,我也遇到一样的问题,在做XML解析时候,报内存溢出!
int xmlLength = this.recoverNetworkBytesOrder(networkOrder); xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), CHARSET); from_appid = new String(Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length), CHARSET);
主要是xmlLength长度换算出来可能太长了,导致内存溢出了!