一. 请求报文变更
请求xml报文结构包含:
1. head报文
2. 业务报文
3. 其他报文
国密改造后,1和3不变,2主要是2个字段:
MsgBody: SM4加密的原业务节点
Sign:对MsgBody 进行SM2签名
二. 关于秘钥
SM4 秘钥: 32位字符,我方告知银行,用于信息的对称加解密
SM2 :
我方:私钥,64位,用于签名; 公钥,130位(含04)给银行。另外P10文件(输入SM2公私钥、DN串,用工具生成)也要给银行,用于制作证书。
银行方: 公钥,130位(含04)字符,会给到我们,另外,公钥相对应的证书也会给我方。
准备4个方法: SM4加密,SM4解密, SM2签名,SM2验签。
三. 关于证书
证书,对公钥的认证,防止合作方抵赖或者坏人对公钥的伪造。
证书越权威,安全性越高;
证书链为NORMAL_CERT(银行方) -> CCAS_COR_CERT(中间证书) -> CCAS_ROOT_CERT(根证书)
校验证书
1. 时间有效性: CertHelper.certDateValidate(SM.NORMAL_CERT, new Date());
2. 证书有效性: 一层一层往上校验,
CertHelper.certSignatureValidate(SM.NORMAL_CERT, Base64.decode(SM.CCAS_COR_CERT)); //校验银行方和中间证书
CertHelper.certSignatureValidate(Base64.decode(SM.CCAS_COR_CERT), Base64.decode(SM.CCAS_ROOT_CERT)); //校验中间证书和根证书
3. 校验签名
signer.verifyWithCert(SM.NORMAL_CERT, signData, response.SIGN.getBytes());
//signData: 需验签的报文(SM4加密) ; response.SIGN: 签名
可以看出,上面解签并没有用到银行给的公钥,走的是证书线路。
其实,证书和公钥是一一对应的。SM.NORMAL_CERT,是打开证书后,你可以看到的几百位的base64后的字符(直接双击打开cer证书,在上方三个tab中点击
详细信息->复制到文件->下一页->选择Base64)。
当然,你忽略证书线路,用公钥也是可以解签的:
/**
* 功能:报文验签
* 输入: msg-需验签的报文、signBase64-签名、 bankPublicKey-银行公钥
* 输出:是否验签通过
*/
public static boolean verifySign(String msg, String signBase64, String bankPublicKey) {
byte[] signature = Base64.decode(signBase64);
byte[] sigSrcData = msg.getBytes();
Signature dv = Signature.getInstance(AlgorithmConstants.SM3withSM2); //验签
ClearKeyParameter privateKey = ClearKeyFunction.loadClear(bankPublicKey, "SM2public");
return dv.verify(privateKey, sigSrcData, signature);
}