mirror of
https://gitee.com/binary/weixin-java-tools.git
synced 2026-03-10 00:13:40 +08:00
@@ -0,0 +1,16 @@
|
||||
package com.github.binarywang.wxpay.v3;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 敏感信息字段
|
||||
* @author zhouyognshen
|
||||
**/
|
||||
@Target({ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SpecEncrypt {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.github.binarywang.wxpay.v3.util;
|
||||
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.github.binarywang.wxpay.v3.SpecEncrypt;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* 微信支付敏感信息加密
|
||||
* 文档见: https://wechatpay-api.gitbook.io/wechatpay-api-v3/qian-ming-zhi-nan-1/min-gan-xin-xi-jia-mi
|
||||
*
|
||||
* @author zhouyongshen
|
||||
**/
|
||||
public class RsaCryptoUtil {
|
||||
|
||||
|
||||
static String JAVA_LANG_STRING = "java.lang.String";
|
||||
|
||||
public static void encryptFields(Object encryptObject, X509Certificate certificate) throws WxPayException {
|
||||
try {
|
||||
encryptField(encryptObject, certificate);
|
||||
} catch (IllegalAccessException | IllegalBlockSizeException e) {
|
||||
throw new WxPayException("敏感信息加密失败", e);
|
||||
} catch (Exception e2) {
|
||||
throw new WxPayException("敏感信息加密失败", e2);
|
||||
}
|
||||
}
|
||||
|
||||
private static void encryptField(Object encryptObject, X509Certificate certificate) throws IllegalAccessException, IllegalBlockSizeException {
|
||||
Class<?> infoClass = encryptObject.getClass();
|
||||
Field[] infoFieldArray = infoClass.getDeclaredFields();
|
||||
for (Field field : infoFieldArray) {
|
||||
if (field.isAnnotationPresent(SpecEncrypt.class)) {
|
||||
//字段使用了@SpecEncrypt进行标识
|
||||
if (field.getType().getTypeName().equals(JAVA_LANG_STRING)) {
|
||||
field.setAccessible(true);
|
||||
Object oldValue = field.get(encryptObject);
|
||||
if (oldValue != null) {
|
||||
String oldStr = (String) oldValue;
|
||||
if (!oldStr.trim().equals("'")) {
|
||||
field.set(encryptObject, encryptOAEP(oldStr, certificate));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
field.setAccessible(true);
|
||||
Object obj = field.get(encryptObject);
|
||||
if (obj != null) {
|
||||
encryptField(field.get(encryptObject), certificate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String encryptOAEP(String message, X509Certificate certificate)
|
||||
throws IllegalBlockSizeException {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, certificate.getPublicKey());
|
||||
|
||||
byte[] data = message.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] ciphertext = cipher.doFinal(data);
|
||||
return Base64.getEncoder().encodeToString(ciphertext);
|
||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
|
||||
throw new RuntimeException("当前Java环境不支持RSA v1.5/OAEP", e);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new IllegalArgumentException("无效的证书", e);
|
||||
} catch (IllegalBlockSizeException | BadPaddingException e) {
|
||||
throw new IllegalBlockSizeException("加密原串的长度不能超过214字节");
|
||||
}
|
||||
}
|
||||
|
||||
public static String decryptOAEP(String ciphertext, PrivateKey privateKey)
|
||||
throws BadPaddingException {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
|
||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
|
||||
byte[] data = Base64.getDecoder().decode(ciphertext);
|
||||
return new String(cipher.doFinal(data), StandardCharsets.UTF_8);
|
||||
} catch (NoSuchPaddingException | NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException("当前Java环境不支持RSA v1.5/OAEP", e);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new IllegalArgumentException("无效的私钥", e);
|
||||
} catch (BadPaddingException | IllegalBlockSizeException e) {
|
||||
throw new BadPaddingException("解密失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user