简而言之:您正在为错误的数据添加时间戳,请参阅答案的底部。
您的签名与 Adobe 的签名之间的主要区别:
Adobe的签名包含一个签名的撤销信息属性;该属性不包含任何实际的撤销信息。
由于此属性是可选的,因此此处不应相关。
您的签名包含签名的签名时间属性。
由于您还嵌入了时间戳,因此签名时间不是必需的,但也不是禁止的。
您的签名的 signatureAlgorithm 值为 1.2.840.113549.1.1.1,即RSA 加密,而 Adobe 的值为 1.2.840.113549.1.1.11,即sha256WithRSAEncryption
在这里,Adobe 的选择肯定是更好的选择,但 Adobe Reader 似乎忽略了您签名中的缺陷:毕竟,它说文档自签名以来没有更改。
在您的签名中,时间戳标记了 PDF 文档的哈希值,即与签名的已签名 messageDigest 属性中的相同,而在 Adobe 的签名中,时间戳标记的是不同的。
砰。这就是问题。诚然,您在最初的问题中说过,但没有引起我的注意:
使用 CryptHashMessage 函数 (SHA256) 创建 pdf 数据的摘要。
使用 CryptRetrieveTimeStamp 函数将此摘要发送到 TSA。我设置了TIMESTAMP_DONT_HASH_DATA标志,这样摘要就不会再次被散列。
这是错误的!根据规范,时间戳作为无符号属性添加:
作为无符号属性的时间戳信息 (PDF 1.6):时间戳记号应符合 RFC 3161,并且应按照 RFC 3161 的附录 A 中的描述计算并嵌入到 PKCS#7 对象中。
(ISO 32000-1第 12.8.3.3.1 节)
*And RFC 3161 states:*
TimeStampToken 中的 messageImprint 字段的值应该是 SignerInfo 中的签名字段值的哈希,用于被标记的签名数据。
(RFC 3161的附录 A )
*Thus, **you are time stamping the wrong hash!** Adobe correctly expects you to time stamp the signature. So you should first create a regular signature, then look up its signature value, hash & time stamp that value, and then add that time stamp to the signature container signer info as unsigned time stamp attribute.*
*Unfortunately I don't know the Windows Crypto API well enough to explain how to do that; I'm more at home in the Java crypto api.*