/** * 对xml消息加密 * * @param appId 应用ID * @param encodingAesKey 加密密钥 * @param xmlContent 原始消息体 * @return aes加密后的消息体 * @throws WeixinException */ public static String aesEncrypt(String appId, String encodingAesKey, String xmlContent) throws WeixinException { byte[] randomBytes = StringUtil.getBytesUtf8(RandomUtil.generateString(32)); byte[] xmlBytes = StringUtil.getBytesUtf8(xmlContent); int xmlLength = xmlBytes.length; byte[] orderBytes = new byte[4]; orderBytes[3] = (byte) (xmlLength & 0xFF); orderBytes[2] = (byte) (xmlLength >> 8 & 0xFF); orderBytes[1] = (byte) (xmlLength >> 16 & 0xFF); orderBytes[0] = (byte) (xmlLength >> 24 & 0xFF); byte[] appidBytes = StringUtil.getBytesUtf8(appId); int byteLength = randomBytes.length + xmlLength + orderBytes.length + appidBytes.length; // ... + pad: 使用自定义的填充方式对明文进行补位填充 byte[] padBytes = PKCS7Encoder.encode(byteLength); // random + endian + xml + appid + pad 获得最终的字节流 byte[] unencrypted = new byte[byteLength + padBytes.length]; byteLength = 0; // src:源数组;srcPos:源数组要复制的起始位置;dest:目的数组;destPos:目的数组放置的起始位置;length:复制的长度 System.arraycopy(randomBytes, 0, unencrypted, byteLength, randomBytes.length); byteLength += randomBytes.length; System.arraycopy(orderBytes, 0, unencrypted, byteLength, orderBytes.length); byteLength += orderBytes.length; System.arraycopy(xmlBytes, 0, unencrypted, byteLength, xmlBytes.length); byteLength += xmlBytes.length; System.arraycopy(appidBytes, 0, unencrypted, byteLength, appidBytes.length); byteLength += appidBytes.length; System.arraycopy(padBytes, 0, unencrypted, byteLength, padBytes.length); try { byte[] aesKey = Base64.decodeBase64(encodingAesKey + "="); // 设置加密模式为AES的CBC模式 Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); SecretKeySpec keySpec = new SecretKeySpec(aesKey, Consts.AES); IvParameterSpec iv = new IvParameterSpec(aesKey, 0, 16); cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv); // 加密 byte[] encrypted = cipher.doFinal(unencrypted); // 使用BASE64对加密后的字符串进行编码 return Base64.encodeBase64String(encrypted); } catch (Exception e) { throw new WeixinException("-40006", "AES加密失败:" + e.getMessage()); } }
/** * 对明文进行加密. * * @param text 需要加密的明文 * @return 加密后base64编码的字符串 * @throws AesException aes加密失败 */ String encrypt(String randomStr, String text) throws AesException { ByteGroup byteCollector = new ByteGroup(); byte[] randomStrBytes = randomStr.getBytes(CHARSET); byte[] textBytes = text.getBytes(CHARSET); byte[] networkBytesOrder = getNetworkBytesOrder(textBytes.length); byte[] appidBytes = appId.getBytes(CHARSET); // randomStr + networkBytesOrder + text + appid byteCollector.addBytes(randomStrBytes); byteCollector.addBytes(networkBytesOrder); byteCollector.addBytes(textBytes); byteCollector.addBytes(appidBytes); // ... + pad: 使用自定义的填充方式对明文进行补位填充 byte[] padBytes = PKCS7Encoder.encode(byteCollector.size()); byteCollector.addBytes(padBytes); // 获得最终的字节流, 未加密 byte[] unencrypted = byteCollector.toBytes(); try { // 设置加密模式为AES的CBC模式 Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES"); IvParameterSpec iv = new IvParameterSpec(aesKey, 0, 16); cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv); // 加密 byte[] encrypted = cipher.doFinal(unencrypted); // 使用BASE64对加密后的字符串进行编码 String base64Encrypted = base64.encodeToString(encrypted); return base64Encrypted; } catch (Exception e) { e.printStackTrace(); throw new AesException(AesException.EncryptAESError); } }