package com.boco.nbd.wios.wx.utils; import com.boco.nbd.cams.core.constant.CamsConstant; import com.ihidea.component.pay.ail.Base64; import com.ihidea.core.util.JSONUtilsEx; import com.ihidea.core.util.StringUtilsEx; import org.apache.commons.lang.StringUtils; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.AlgorithmParameters; import java.security.Security; import java.util.Arrays; import java.util.Map; /** * 微信解密工具类 * * @author lvpeng * @version [版本号] * @date 2017年11月6日 */ public class WeChatDecryptUtils { private static final Logger logger = LoggerFactory.getLogger(WeChatDecryptUtils.class); public static Map<String, Object> decode(String sessionKey, String encryptedData, String iv) { //转义字符处理 encryptedData = StringUtilsEx.unescapeXss(encryptedData); iv = StringUtilsEx.unescapeXss(iv); sessionKey = StringUtilsEx.unescapeXss(sessionKey); byte[] decrypted = decrypt(sessionKey, encryptedData, iv); if (null != decrypted && decrypted.length > 0) { String jsonStr = new String(decodeForWxPKCS7(decrypted)); if (StringUtils.isNotBlank(jsonStr)) { return JSONUtilsEx.deserialize(jsonStr, Map.class); } } return null; } /** * AES解密 * * @author lvpeng * @date 2017年9月7日 * @param sessionKey 密钥 * @param encryptedData 加密内容 * @param iv 加密算法的偏移量 * @return */ public static byte[] decrypt(String sessionKey, String encryptedData, String iv) { // logger.error("sessionKey:{},encryptedData:{},iv:{}", new String[]{sessionKey, encryptedData, iv}); byte[] aesKey = Base64.decode(sessionKey); byte[] aesData = Base64.decode(encryptedData); byte[] aesIv = Base64.decode(iv); Security.addProvider(new BouncyCastleProvider()); try { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); SecretKeySpec keyspec = new SecretKeySpec(aesKey, "AES"); IvParameterSpec ivspec = new IvParameterSpec(aesIv); cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec); byte[] original = cipher.doFinal(aesData); return original; } catch (Exception e) { logger.error("解密失败"); return null; } } /** * 删除解密后明文的补位字符 * * @param decrypted 解密后的明文 * @return 删除补位字符后的明文 */ private static byte[] decodeForWxPKCS7(byte[] decrypted) { int pad = decrypted[decrypted.length - 1]; if (pad < 1 || pad > 32) { pad = 0; } return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad); } /** * 解密微信用户数据 * @param sessionkey * @param encryptedData * @param iv * @return */ @SuppressWarnings("unchecked") public static String decryptWxUser(String sessionkey, String encryptedData, String iv) { if(StringUtils.isEmpty(sessionkey) || StringUtils.isEmpty(encryptedData) || StringUtils.isEmpty(iv)){ return null; } // 被加密的数据 byte[] dataByte = Base64.decode(encryptedData); // 加密秘钥 byte[] keyByte = Base64.decode(sessionkey); // 偏移量 byte[] ivByte = Base64.decode(iv); try { // 如果密钥不足16位,那么就补足. 这个if 中的内容很重要 int base = 16; if (keyByte.length % base != 0) { int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0); byte[] temp = new byte[groups * base]; Arrays.fill(temp, (byte) 0); System.arraycopy(keyByte, 0, temp, 0, keyByte.length); keyByte = temp; } // 初始化 Security.addProvider(new BouncyCastleProvider()); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC"); SecretKeySpec spec = new SecretKeySpec(keyByte, "AES"); AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES"); parameters.init(new IvParameterSpec(ivByte)); cipher.init(Cipher.DECRYPT_MODE, spec, parameters); byte[] resultByte = cipher.doFinal(dataByte); if (null != resultByte && resultByte.length > 0) { String result = new String(resultByte, StandardCharsets.UTF_8); Map<String, String> resultMap = JSONUtilsEx.deserialize(result, Map.class); return resultMap!=null && resultMap.get("purePhoneNumber")!=null? resultMap.get("purePhoneNumber") : null; } } catch (Exception e) { e.printStackTrace(); } return null; } }