- 请问我到底要如何拼接原始数据进行验签?
https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/api_security.htmlI请求处理https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/getting_started/api_signature.htmlhttps://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/getting_started/api_signature.htmlhttps://developers.weixin.qq.com/miniprogram/dev/framework/https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/getting_started/api_signature.html 图1 这是腾讯的文档,告诉我我要这样拼接 [图片] 图2 这也是腾讯的文档,告诉我,我要这样拼接 [图片] 两种方式我都试了,都验签失败,但是图2的提供的demo代码可以验签通过,我是真的服气了
2023-11-29 - API验签,服务端用rsa失败
图1、2:没有RSAKey.getParams()方法,文档中未注明,这个方法只在jdk1.8_3之后的版本提供 [图片] [图片] 问题2:服务器上jdk版本为1.8_3之后的,也验签失败,文档中提供demo的main方法也无法跑通(响应时间已经缓过了) package com.example.demo;// RSAwithSHA256 import com.google.gson.JsonObject; import com.tencent.kona.KonaProvider; import org.bouncycastle.jce.provider.BouncyCastleProvider; import java.io.ByteArrayInputStream; import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.security.Provider; import java.security.Security; import java.security.Signature; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.interfaces.RSAKey; import java.security.spec.MGF1ParameterSpec; import java.security.spec.PSSParameterSpec; import java.util.Base64; 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); 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" + "MIID0jCCArqgAwIBAgIUeE+Yy7vM/o+eHHsfM+1bGJJEZTQwDQYJKoZIhvcNAQEL\n" + "BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT\n" + "FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg\n" + "Q0EwHhcNMjIwOTA1MDgzOTIyWhcNMjcwOTA0MDgzOTIyWjBkMRswGQYDVQQDDBJ3\n" + "eGQ5MzBlYTVkNWEyNThmNGYxFTATBgNVBAoMDFRlbmNlbnQgSW5jLjEOMAwGA1UE\n" + "CwwFV3hnTXAxCzAJBgNVBAYMAkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJ\n" + "KoZIhvcNAQEBBQADggEPADCCAQoCggEBAM5D9qlkCmk1kr3FpF0e9pc3kGsvz5RA\n" + "0/YRny9xPKIyV2UVMDZvRQ+mDHsiQQFE6etg457KFYSxTDKtItbdl6hJQVGeAvg0\n" + "mqPYE9SkHRGTfL/AnXRbKBG2GC2OcaPSAprsLOersjay2me+9pF8VHybV8aox78A\n" + "NsU75G/OO3V1iEE0s5Pmglqk8DEiw9gB/dGJzsNfXwzvyJyiUP9ZujYexyjsS+/Z\n" + "GdSOUkqL/th+16yHj8alcdyga6YGfWEDyWkt/i/B28cwx4nzwk8xgrurifPaLuMk\n" + "0+9wJQLCfAn/f7zyHrC8PcD1XvvRt9VBNMBASXs3710ODyyVf2lkMgkCAwEAAaOB\n" + "gTB/MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgTwMGUGA1UdHwReMFwwWqBYoFaGVGh0\n" + "dHA6Ly9ldmNhLml0cnVzLmNvbS5jbi9wdWJsaWMvaXRydXNjcmw/Q0E9MUJENDIy\n" + "MEU1MERCQzA0QjA2QUQzOTc1NDk4NDZDMDFDM0U4RUJEMjANBgkqhkiG9w0BAQsF\n" + "AAOCAQEAL2MK9tYu+ljLVBlSbfEeaKyF07TN+G31Ya5NBzeS1ZCx4joUEIyACWmG\n" + "fUkKNKiKV+EMzxeEhKRso1Qif3E7Ipl+PQBoQw6OSR/jFHciYurnGR9CLkL03Zo1\n" + "qw1Xetv9OipsvlpA0SOWc207e/XpGdm8C7FMXM6bzvVp8I/STTjC1vqjIZu9WavI\n" + "RgGM4jyAPz2XogUq0BNijef8BXbbav9fAsXjHSwn5BQv4iLms3fiLm/eoyQ6dZ2R\n" + "oTudrlcyr1bG4vwETLmHF+3yfVp9dpvJ+lyfiviwDwyfa8t2WlJm27DuF4vWoxir\n" + "mjgj9tDutIFqxLIovLyg3uiAYtSQ/Q==\n" + "-----END CERTIFICATE-----"; ctx.addProperty("local_certificate",localCertificate); ctx.addProperty("local_sym_sn","79ba700ea147819f640941bceb38b1d1"); ctx.addProperty("local_appid","wxba6223c06417af7b"); ctx.addProperty("url_path","https://api.weixin.qq.com/wxa/getuserriskrank"); return ctx; } private static JsonObject getResp(){ JsonObject resp = new JsonObject(); resp.addProperty("resp_appid","wxba6223c06417af7b"); resp.addProperty("resp_ts",System.currentTimeMillis() / 1000); resp.addProperty("resp_sn","79ba700ea147819f640941bceb38b1d1"); resp.addProperty("resp_sig","Ht0VfQkkEweJ4hU266C14Aj64H9AXfkwNi5zxUZETCvR2svU1ZYdosDhFX/voLj1TyszqKsVxAlENGt7PPZZ8RQX7jnA4SKhiPUhW4LTbyTenisHJ+ohSfDjYnXavjQsBHspFS+BlPHuSSJ2xyQzw1+HuC6nid09ZL4FnGSYo4OI5MJrSb9xLzIVZMIDuUQchGKi/KaB1KzxECLEZcfjqbAgmxC7qOmuBLyO1WkHYDM95NJrHJWba5xv4wrwPru9yYTJSNRnlM+zrW5w9pOubC4Jtj3szTAEuOz9AcqUmgaAvMLNAIa8hfODLRe3n/cu4SgYlN/ZkNRU4QXVNbPGMg=="); resp.addProperty("resp_deprecated_sn","2171af9cdf1d7404423852e7e183d852"); resp.addProperty("resp_deprecated_sig","ZP1OODikAOePc+YJUMLxunF6xV05kextO/T1fy5lWv/CwV6OCsPBRM2xRRCi+B4lYXbbfYDdjzCz5BIAWEwIdjMlg/IHcJVHhRNAlKt5A3zvzfaJa5IJQel7xuUEXk/B6KVyEb41PbzrptjUGqWyTFMrjxQ4ThJfCuYocnUng7OuDU95enMqK2hZpO8o7kFW638BAwKDSiFNEwEJDWYkLz0kEw7ma3keezm4YHYKfJmjChK39tmZld7Rw/yrV1U9RiL/DO5ayP9VmrQkT/vYrPKyqI4/xKrIaTq44jFYTPIJKdU2OnLt6kjqwp2hvCzMuJdjRcrvzhWJ2A8xZ5hI2w=="); resp.addProperty("resp_data","{\"iv\":\"r2WDQt56rEAmMuoR\",\"data\":\"HExs66Ik3el+iM4IpeQ7SMEN934FRLFYOd3EmeaIrpP4EPTHckoco6O+PaoRZRa3lqaPRZT7r52f7LUok6gLxc6cdR8C4vpIIfh4xfLC4L7FNy9GbuMK1hcoi8b7gkWJcwZMkuCFNEDmqn3T49oWzAQOrY4LZnnnykv6oUJotdAsnKvmoJkLK7hRh7M2B1d2UnTnRuoIyarXc5Iojwoghx4BOvnV\",\"authtag\":\"z2BFD8QctKXTuBlhICGOjQ==\"}"); return resp; } public static void main(String[] args) { JsonObject resp = getResp(); JsonObject ctx = getCtx(); boolean res = checkSignature(ctx,resp); System.out.println(res); } }
2023-11-28