public class RSA_Verify {
public static boolean checkSignature(JsonObject ctx,JsonObject resp){
String signature = null;
boolean result = false;
// 开发者本地信息
String local_appid = ctx.get("local_appid").getAsString();
String url_path = ctx.get("url_path").getAsString();
String local_sym_sn = ctx.get("local_sym_sn").getAsString();
String local_certificate = ctx.get("local_certificate").getAsString();
long respTs = resp.get("resp_ts").getAsLong();
String respAppid = resp.get("resp_appid").getAsString();
String respSn = resp.get("resp_sn").getAsString();
String respSig = resp.get("resp_sig").getAsString();
String respDeprecatedSn = resp.get("resp_deprecated_sn").getAsString();
String respDeprecatedSig = resp.get("resp_deprecated_sig").getAsString();
String respData = resp.get("resp_data").getAsString();
long localTs = System.currentTimeMillis() / 1000;
// 安全检查,根据业务实际需求判断
if (respAppid != local_appid || // 回包appid不正确
localTs - respTs > 300){ // 回包时间超过5分钟
System.out.println("安全字段校验失败");
return result;
}
if(local_sym_sn == respSn){
signature = respSig;
}else if(local_sym_sn == respDeprecatedSn){
System.out.println("平台证书即将过期,请及时更换"); // 本地证书编号与即将过期编号一致,需及时更换
signature = respDeprecatedSig;
}else{
System.out.println("sn不匹配");
return result;
}
String payload = url_path + "\n" + local_appid + "\n" + respTs + "\n" + respData;
byte[] dataBuffer = payload.getBytes(StandardCharsets.UTF_8);
// 确保加载 BouncyCastle 提供程序
Security.addProvider(new BouncyCastleProvider());
try{
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
ByteArrayInputStream inputStream = new ByteArrayInputStream(local_certificate.getBytes());
X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(inputStream);
Signature verifier = Signature.getInstance("RSASSA-PSS");
PSSParameterSpec pssParameterSpec = new PSSParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, 1);
verifier.setParameter(pssParameterSpec);
verifier.initVerify(certificate);
verifier.update(dataBuffer);
byte[] sig_buffer = Base64.getDecoder().decode(signature);
result = verifier.verify(sig_buffer);
}catch (Exception e){
e.printStackTrace();
}
return result;
}
private static JsonObject getCtx(){
JsonObject ctx = new JsonObject();
// 仅做演示,敏感信息请勿硬编码
String localCertificate = "-----BEGIN CERTIFICATE-----\n" +
"MIID9DCCAtygAwIBAgIUaB2siCgYGWdiA2mdSGpWPqwlKDYwDQYJKoZIhvcNAQEL\n" +
"BQAwbTELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5nRG9uZzERMA8GA1UEBwwI\n" +
省略....
"JXBtYJRsH6xQXLW6sCL8mh/QsVKkjHeYgN0qz1e585JP69uCyWzYNVxhNr6U6HQK\n" +
"vozFTehwlm8=\n" +
"-----END CERTIFICATE-----";
ctx.addProperty("local_certificate",localCertificate);
ctx.addProperty("local_sym_sn","d7914ee8f4XXXXXXXXXXX");
ctx.addProperty("local_appid","wx66f8f5a50d26e3eb");
ctx.addProperty("url_path","https://api.weixin.qq.com/wxa/business/getuserphonenumber");
return ctx;
}
private static JsonObject getResp(){
JsonObject resp = new JsonObject();
resp.addProperty("resp_appid","wx66f8f5XXXXXXXX");
resp.addProperty("resp_ts",1732794186);
resp.addProperty("resp_sn","d7914ee8f41XXXXXXXXXX");
resp.addProperty("resp_sig","nOQvsfQbXcJTuaS61jx0lDXXXXXXXX");
resp.addProperty("resp_deprecated_sn","");
resp.addProperty("resp_deprecated_sig","");
resp.addProperty("resp_data","{\"authtag\":\"MyejXXXXXFw==\",\"data\":\"8Wl3F4NVXXXXXiXvz XXXXXX 6rBykFSB8CmZrMN//OfTov0=\",\"iv\":\"3MaXXXXXX+mlE\"}");
return resp;
}
public static void main(String[] args) {
JsonObject resp = getResp();
JsonObject ctx = getCtx();
boolean res = checkSignature(ctx,resp);
System.out.println(res);
}
}
返回:false
但是我通过解密的demo示例,能够成功解析数据,并且能够正确的获取手机号:
?