AlipaySDKNet 是 .NET 平台下用于对接支付宝支付的官方 SDKAlipay SDK for .NET 让您不用复杂编程即可访问支付宝开放平台开放的各项能力,SDK可以自动帮您满足能力调用过程中所需的证书校验、加签、验签、发送HTTP请求等非功能性要求其 Nuget 链接如下:https://www.nuget.org/packages/AlipaySDKNet.Standard GitHub 开源地址为:https://github.com/alipay/alipay-sdk-net-all ,下面我们就来说一说关于支付宝的公钥与私钥如何查看?我们一起去了解并探讨一下这个问题吧!
支付宝的公钥与私钥如何查看
AlipaySDKNet 是 .NET 平台下用于对接支付宝支付的官方 SDK。Alipay SDK for .NET 让您不用复杂编程即可访问支付宝开放平台开放的各项能力,SDK可以自动帮您满足能力调用过程中所需的证书校验、加签、验签、发送HTTP请求等非功能性要求。其 Nuget 链接如下:https://www.nuget.org/packages/AlipaySDKNet.Standard 。GitHub 开源地址为:https://github.com/alipay/alipay-sdk-net-all 。
要在程序中集成支付宝支付其实并不困难,只要谨记 .NET 程序要用的私钥格式是 PKCS1 且不把参数搞混问题应该都不大。
但是今天,却遇到一个大问题:之前正常工作的代码在更换了账户配置(APPID、私钥等)之后竟然报错了。
Aop.Api.AopException: RSA签名遭遇异常,请检查私钥格式是否正确。Index was outside the bounds of the array.
根据报错时的堆栈信息,该错误来自于方法:
Aop.Api.Util.Asymmetric.RSAEncryptor.BuildRSAServiceProvider
本着先从自己找原因的原则冲头到尾检查了配置参数,PKCS1 格式是对的、私钥是对的、公钥是对的甚至点鼠标的手势也是对的。
尝试了 Java 语言的 DEMO (其采用的是 PKCS8 格式),这套参数也是可以正常工作的那就说明密钥本身是没问题的。
无奈之下只能通过 GitHub 将代码克隆到本地并引入项目开始调试。找到报错断点位于 RSAEncryptor 的 BuildRSAServiceProvider 方法:
https://github.com/alipay/alipay-sdk-net-all/blob/98fc187884d628d4268504bc0b93eb9a1aae417a/AlipaySDKNet.Standard/Util/Asymmetric/RSAEncryptor.cs#L234
这个方法的作用是读取 PKCS1 格式私钥并构建 RSACryptoServiceProvider ,但转换过程略显过时。其实,.NET 在 netstandard-2.1 时已经提供了名为 ImportRSAprivateKey 的方法用于导入密钥,这段代码可以直接被替换掉。
首先需要将 AlipaySDKNet.Standard 的目标框架修改为 netstandard2.1 ,接着使用以下代码替换 BuildRSAServiceProvider 方法:
private static RSACryptoServiceProvider BuildRSAServiceProvider(byte[] privateKey)
{
var rsa = new RSACryptoServiceProvider();
rsa.ImportRSAPrivateKey(privateKey, out _);
return rsa;
}
再次编译项目,已经可以正常下单使用了。
问题找到了,然后呢?换一个密钥也许是最简单的方案。想要向阿里反馈这个问题,却发现该仓库并未开放 Issues 功能。我也想退而求其次,不要在项目中引入整个 SDK 的源代码(它太大了,有一万五千多个文件)只对 SDK 打补丁。但我发现这很难做到:DefaultAopClient 的实现看上去很复杂,而且 BuildRSAServiceProvider 被定义为了一个私有的静态方法。
如何复现这个问题?我当然不能把我现在使用的私钥共享出来,但我做了一些工作又生成了一个会报错的私钥(PKCS1 格式):
MIIEowIBAAKCAQEApkzj3sk hpd2e0d8BUbDkuL6khflsJLzoQwGq25mm5fn2MDN3MPl/h0/XtWoM6OOIigvQFFj295UxN/I4oGrWL/oYA0g2MWlttLHPZ2ivhCSSizw9OJtAg8NgmkDM8dygAhyUQja2ZoACWrNrQa4DC10GXpRi/85ZGMEBcKZnUwlwYan31rVtgdULZ0l W3yiWYtMaGKoT/BWQZ3bjUzCU/OxcuCK6Z/YUho65YxJa/zQdTmduxW7ghgGILqvoyh1PS1Zb JeCJ3t6rxsoCDfKV7ldMUrWYKjMewvj6JritxgsmF/E80f12mMqDimLhJX8nTqQQ2kajEazkvZQNxaQIDAQABAoIBAACq2FNBjX2ux vwun u7AP/4y I5wQRYubnjHNNqx2 u1B0XZ8gLiEZ7vIre1RRuLVMYfwpF3R/bOmpWD4IdS6S/pS8GMCl8mdMaz5FDq0ileO0UHc7HWLfupcmYrvndf8riYHnvjEXXB6tjgu tiheWlPr2L3uFUXg29hGEqW98dSffYIWrdYOcFa1wWnR6w FOEXqGcAppKKADosHCqA8S5M tPcGbZ/PIJwcJEx GsXsy1aoslB6hgAyJOmnY2w2o5V30I1QzhgiwCGAHK4pNABRtXwzGnSjfzdkrUb0irytvFrHj/RMuYHFaEJ8cSnc/c2sh87Zia5e6H6I 00CgYEA1d6oRlMCpfleUee0jl7KsGnqdoquipC7vNVjfPsSuGbXy9NRt/N4rSymfHsQA8zExmHfQjtk3kS64HXkUZRVrACNCLM6mgcEEshixRntaZJdA RruPb45JBkhnjtmmQJ4BY06GTqtsflnaPJEv5wvReBlByThOcHI fcOeUYfGcCgYEAxw9VAZfXxeVGT/ 7skxxu1568OyrS7tysaMVy6Uufztd6hY3ZT VV1QFxj8fku9miVFLCvhU4Z3HrahRmGNZ7XT0Cgm8ZhFhKKR7gQlAMAmLeSGgAUbjQ3BEKG5NXKqsFpAisoEV5/MoZ3eQuVGQ5JApbKZlhIVOX2Kq9gqmAa8CgYEAhfT9n3a1DPKBsnmX7SjQeekNc4xvwNjgzmk19H1qf1fjSIanA7obVxTFfuix4j9q7Ps2lMyQ5GtWRetxw tOMfryW4WvafSFB6K9wsj3nI2RdzOmiWcgBEGwxU2PPYn1aYdfQkSbgzr3xmJlOmFmifnkLroraC4wmbvLg/PL/3cCgYA25PKDSvV1HIIkY5jGVbBzhF2Q/SNL8jhx5lCHZVkKOzvt5wyFvmAXwhMJlbTGV4DGU4XHU65Mva8oI6fEx3kwM7Vs4zxyRU6u35Uzg3KRDMDKucwfLgZUPax HdT1vhdQ7ZSz90csPPEif2WIxYaYkWzrCoQqZHy1b0dILK2U/wKBgFAmZrWiB1mLp8hdLp49Fctf KKH16t6CkhEzh0s ElaRcuLQ/ m5nGSxBbPm7QeLxZBD12ugnj0czcRPfjWDNDTHghnXr DNsVuQ8oUdrCQpwHgHpoeOzZaoX1RSSRceuZOiRaDJM/rf1CGi/LcXIE0YvlJF/eDCTlx6cOTFn7T
你也可以使用以下代码尝试生成并测试,该代码循环100次,并尝试用阿里 SDK 提供的方法对密钥进行转换:
for (int i = 0; i < 100; i )
{
var rsa = RSA.Create();
var keys = rsa.ExportRSAPrivateKey();
try
{
BuildRSAServiceProvider(keys);
}
catch (Exception ex)
{
Console.WriteLine(Convert.ToBase64String(keys));
}
}
经测试,一百次生成中大概会有 2-4 次遇到异常密钥。
如果你遇到了和笔者一样的问题,并且通读本文解决了你的问题。那么恭喜你,你大概就是天选之子,下班后去买彩吧,说不定能中大奖。
后记受制于笔者的浅薄,本文并没有找到 BuildRSAServiceProvider 不能正确加载私钥的原因,但使用另一种方法规避了该问题。这让我更加坚信,即便是大厂的作品也不是完美无瑕。
简单总结一下:如果你遇到了本文所述的问题,那么就重置一下密钥吧。植发毕竟太贵了。
阅读原文:支付宝 .NET SDK 报错:RSA签名遭遇异常,请检查私钥格式是否正确。-码农很忙
,