一.业务背景
由于业务中接触到来账平台来账消息这一业务,在其中涉及到非对称加密方式的加解密,对支付宝来的消息要核实消息来源,所有要对来源的签名进行验签。需要用到支付宝的公钥,但是我作为业务开发方没有权限直接拿到公钥,所有就要用到阿里集团的KeyCenter秘钥管理平台,它分配了我一个公钥的名称,我就能用该公钥的名称利用keyCenter的接口捞出公钥并进行验签(操作黑盒)。加密方式主要采用DSA。
二.问题出现
在支付宝发给过我一则日常环境的通知后,我就用来账平台的这则通知拿来测试。主要是本地上写了Junit单测来模拟验签,能验签成功。自己写了一个脚本,向服务器上的Servlet发起通知,却一直报错Invalid signature format。这让我一度想到环境编码,或者是keyCenter调用方式等原因。
三.排查问题的大致步骤
1. 查看报错Invalid signature format的代码位置
TranscodeUtil.rsToSignature()函数中抛出的异常
public static byte[] rsToSignature(byte[] rs) throws Exception {
if ((rs == null) || (rs.length != 40)) {
throw new Exception("Invalid signature format");
}
2. Debug分析出问题出现的位置
由此倒推verifyByTranscode()中 byte[] signedRS的长度不对
public boolean verifyByTranscode(byte[] bytesToVerify, byte[] signature, String keyRef) throws Exception {
byte[] signedRS = Base64.decodeBase64(TranscodeUtil.decodeUpperCase(new String(signature)));
byte[] signed = TranscodeUtil.rsToSignature(signedRS);
return verifyBySignature(bytesToVerify, signed, keyRef);
}
只是粗略的大概看了下传来的signature的值,本地和服务器上是一样的。也对了下服务器收到的所有参数,也都与本地一致。通过了一系列对本地Junit数据和远程服务器上的代码的Debug,检查Base64.decodeBase64()中的逻辑
@Override
public byte[] decode(final byte[] pArray) {
if (pArray == null || pArray.length ==