package com.dsh.activity.util.wx;
|
|
import javax.crypto.Cipher;
|
import javax.crypto.NoSuchPaddingException;
|
import javax.crypto.spec.GCMParameterSpec;
|
import javax.crypto.spec.SecretKeySpec;
|
import java.nio.charset.StandardCharsets;
|
import java.security.GeneralSecurityException;
|
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidKeyException;
|
import java.security.NoSuchAlgorithmException;
|
import java.util.Base64;
|
|
/**
|
* 微信支付V3 AES解密工具类 (AEAD_AES_256_GCM)
|
*/
|
public class WxPayAesUtil {
|
|
private static final String ALGORITHM = "AES/GCM/NoPadding";
|
private static final int TAG_LENGTH_BIT = 128; // GCM认证标签长度,固定为128位
|
private static final int NONCE_LENGTH_BYTE = 12; // GCM随机串长度,固定为12字节
|
private static final String TRANSFORMATION = "AES/GCM/NoPadding"; // 算法/模式/填充
|
|
/**
|
* 解密微信支付回调通知中的加密信息
|
*
|
* @param apiV3Key APIv3密钥 (来自 WxV3PayConfig)
|
* @param associatedData 附加数据 (resource.associated_data)
|
* @param nonce 随机串 (resource.nonce)
|
* @param ciphertext 密文 (resource.ciphertext),Base64编码
|
* @return 解密后的明文字符串
|
* @throws GeneralSecurityException 解密失败时抛出异常
|
*/
|
public static String decrypt(String apiV3Key, String associatedData, String nonce, String ciphertext)
|
throws GeneralSecurityException {
|
try {
|
SecretKeySpec key = new SecretKeySpec(apiV3Key.getBytes(StandardCharsets.UTF_8), "AES");
|
GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce.getBytes(StandardCharsets.UTF_8));
|
|
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
|
cipher.init(Cipher.DECRYPT_MODE, key, spec);
|
cipher.updateAAD(associatedData.getBytes(StandardCharsets.UTF_8)); // 设置附加认证数据
|
|
byte[] decodedCiphertext = Base64.getDecoder().decode(ciphertext);
|
byte[] decryptedBytes = cipher.doFinal(decodedCiphertext);
|
|
return new String(decryptedBytes, StandardCharsets.UTF_8);
|
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
|
throw new IllegalStateException("当前JDK环境不支持AEAD_AES_256_GCM", e);
|
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
|
throw new IllegalArgumentException("无效的密钥或GCM参数", e);
|
} catch (Exception e) {
|
// 包括 BadPaddingException 等解密失败的情况
|
throw new GeneralSecurityException("AES/GCM 解密失败", e);
|
}
|
}
|
}
|