验证特定伙伴AS2 MDN签名时CryptMsgControl返回CRYPT_E_SIGNER_NOT_FOUND
问题解答
1. CRYPT_E_SIGNER_NOT_FOUND错误的可能原因
- 证书匹配偏差:使用
CertGetSubjectCertificateFromStore读取证书时,该API依赖主题字段匹配,若伙伴证书的主题字段(如CN、OU)与你存储中的证书存在细微差异(大小写、空格、字段顺序不同),会导致读取的证书不符或读取失败。 - 证书链不完整:伙伴的签名证书依赖中间CA证书,但你的Windows证书存储中缺少该中间CA证书,
CryptMsgControl无法构建完整信任链,进而判定签名者证书未找到。 - 签名者标识不匹配:MDN签名属性里的签名者信息(颁发者、序列号)与你读取的证书不一致,比如伙伴更新了证书但未同步,或实际签名用了另一证书却告知旧证书信息。
- 存储位置错误:你读取证书的存储位置(Current User/Local Machine)不对,伙伴证书实际在另一存储中,导致读取失败。
- 证书状态异常:证书过期或被吊销时,部分场景下
CryptMsgControl可能返回该错误而非明确的过期/吊销提示,需确认证书状态。
2. 进一步诊断与记录的方法
- 比对证书详细信息:读取证书后,用
CertGetNameString获取主题、颁发者字符串,CryptGetHashParam获取证书指纹,与伙伴提供的信息逐一比对,确认一致性。 - 开启CryptoAPI调试日志:修改注册表启用调试日志:
日志生成在HKEY_LOCAL_MACHINE\Software\Microsoft\Cryptography\OID\EncodingType 0\CryptMsgVerifySignature 添加DWORD值"DebugLogLevel",设为0x00000003%windir%\system32\catroot2\cryptmsg.log,可查看验证过程中具体哪一步找不到签名者证书。 - 手动构建证书链:调用
CertGetCertificateChainAPI手动构建证书链,检查是否能成功建立信任,是否缺少中间证书。 - 解析MDN签名结构:用
CryptMsgGetParam获取MDN中的CMSG_SIGNER_INFO结构,对比其中的颁发者和序列号与你读取的证书是否一致,示例代码:CMSG_SIGNER_INFO signerInfo; DWORD dwSignerInfoSize = sizeof(CMSG_SIGNER_INFO); if (CryptMsgGetParam(m_hCryptMsg, CMSG_SIGNER_INFO_PARAM, 0, &signerInfo, &dwSignerInfoSize)) { // 打印signerInfo.Issuer和signerInfo.SerialNumber } - 直接用证书文件验证:将伙伴提供的证书导入临时存储,直接用该证书调用
CryptMsgControl,排除存储读取环节的问题。
3. CryptMsgControl的已知兼容性问题
- 非标准ASN.1编码:部分伙伴生成的MDN签名采用非标准ASN.1编码,或包含CryptoAPI不支持的自定义签名属性,导致无法正确解析签名者信息。
- 密钥算法兼容性:若伙伴使用了CryptoAPI不完全支持的密钥算法(如特殊ECDSA曲线),
CryptMsgControl可能无法识别证书,返回签名者未找到错误。 - MIME格式错误:AS2 MDN为MIME格式消息,若伙伴的MDN存在MIME封装错误(边界标记、Content-Type头不正确),会导致
CryptMsgOpenToDecode无法正确解析消息,后续验证自然失败。
内容的提问来源于stack exchange,提问作者Mehul
相关产品推荐
相关产品推荐

