/** * 对密文进行解密. * * @param text 需要解密的密文 * @return 解密得到的明文 * @throws AesException aes解密失败 */ String decrypt(String text) throws AesException { 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_appid; try { // 去除补位字符 byte[] bytes = PKCS7Encoder.decode(original); // 分离16位随机字符串,网络字节序和AppId byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20); int xmlLength = recoverNetworkBytesOrder(networkOrder); xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), CHARSET); from_appid = new String(Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length), CHARSET); } catch (Exception e) { e.printStackTrace(); throw new AesException(AesException.IllegalBuffer); } // appid不相同的情况 if (!from_appid.equals(appId)) { throw new AesException(AesException.ValidateAppidError); } return xmlContent; }
/** * 对AES消息解密 * * @param appId * @param encodingAesKey aes加密的密钥 * @param encryptContent 加密的消息体 * @return 解密后的字符 * @throws WeixinException */ public static String aesDecrypt(String appId, String encodingAesKey, String encryptContent) throws WeixinException { byte[] aesKey = Base64.decodeBase64(encodingAesKey + "="); byte[] original; try { // 设置解密模式为AES的CBC模式 Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); SecretKeySpec key_spec = new SecretKeySpec(aesKey, Consts.AES); IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16)); cipher.init(Cipher.DECRYPT_MODE, key_spec, iv); // 使用BASE64对密文进行解码 byte[] encrypted = Base64.decodeBase64(encryptContent); // 解密 original = cipher.doFinal(encrypted); } catch (Exception e) { throw new WeixinException("-40007", "AES解密失败" + e.getMessage()); } String xmlContent, fromAppId; try { // 去除补位字符 byte[] bytes = PKCS7Encoder.decode(original); // 获取表示xml长度的字节数组 byte[] lengthByte = Arrays.copyOfRange(bytes, 16, 20); // 获取xml消息主体的长度(byte[]2int) // http://my.oschina.net/u/169390/blog/97495 int xmlLength = lengthByte[3] & 0xff | (lengthByte[2] & 0xff) << 8 | (lengthByte[1] & 0xff) << 16 | (lengthByte[0] & 0xff) << 24; xmlContent = StringUtil.newStringUtf8(Arrays.copyOfRange(bytes, 20, 20 + xmlLength)); fromAppId = StringUtil.newStringUtf8(Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length)); } catch (Exception e) { throw new WeixinException("-40008", "xml内容不合法" + e.getMessage()); } // 校验appId是否一致 if (!fromAppId.trim().equals(appId)) { throw new WeixinException( "-40005", "校验AppID失败,expect " + appId + ",but actual is " + fromAppId); } return xmlContent; }