使用BouncyCastle验证零长度文件分离签名出现摘要不匹配如何处理
问题根因
该异常由bc-csharp对零长度待校验内容的处理逻辑缺陷导致:默认双参数重载的CmsSignedData构造方法遇到空字节数组时,会跳过待校验内容的消息摘要计算步骤,最终导致本地计算出的摘要和签名中存储的摘要不匹配,抛出校验失败异常。非零长度内容不会触发该逻辑缺陷,所以能正常校验通过。
修复方案
只需对零长度输入做特殊兼容,显式强制要求BouncyCastle计算空内容的摘要即可,修改后的代码如下:
private static bool VerifyDetachedSignature(byte[] fileRawBytes, string sign) { try { var signatureFileRawBytes = Convert.FromBase64String(sign); CmsSignedData cms; // 零长度文件特殊兼容 if (fileRawBytes == null || fileRawBytes.Length == 0) { // 第三个参数传true强制计算空内容的摘要 cms = new CmsSignedData(new CmsProcessableByteArray(Array.Empty<byte>()), signatureFileRawBytes, true); } else { cms = new CmsSignedData(new CmsProcessableByteArray(fileRawBytes), signatureFileRawBytes); } var signers = cms.GetSignerInfos(); var certificates = cms.GetCertificates("Collection"); foreach (SignerInformation signer in signers.GetSigners()) { var certList = new ArrayList(certificates.GetMatches(signer.SignerID)); var cert = (X509Certificate)certList[0]; if (cert == null) throw new NullReferenceException(); signer.Verify(cert.GetPublicKey()); } return true; } catch (Exception) { return false; } }
补充说明
- 如果生成零长度文件签名的逻辑也是基于bc-csharp实现,建议生成签名时也用相同的兼容逻辑,保证签名、校验两端的处理逻辑一致
- 该修复不会影响原有非零长度文件的签名校验逻辑,原有正常场景的兼容性不受影响
内容的提问来源于stack exchange,提问作者Alexey2040
相关产品推荐
相关产品推荐

