我尝试了很多方法来验证签名,但都没有成功。
这并不奇怪:您的签名无效。在 PDF 签名字段值中,签名时间为 2020/06/11 09:28:35 GMT,但您的签名证书在 2020/06/11 09:29:44 GMT 之前有效,而不是在 2020/06/11 09 之后格林威治标准时间:59:44。因此,在声明的签名时间,您的签名者证书尚未生效,无法创建有效签名。
显然,您使用的签名服务会在您对它的签名请求到达时及时创建一个短期证书。不幸的是,这是在 iText 在签名过程开始时存储为 PDF 中的签名时间之后。
因此,解决问题的一种方法是告诉 iText 在未来稍微使用一段时间(例如两分钟)。
你可以通过PdfSignatureAppearance方法setSignDate来做到这一点。
您的签名实际上也违反了规范中的一个建议:上述存储在签名字段值字典中的签名时间应该仅在签名时间不可用时使用签名(嵌入的签名容器)。但是,在您的情况下,嵌入式签名容器确实包含一个 signingTime 签名属性,其值为 11/06/2020 09:29:44 GMT,它在证书有效期开始之前不是。
这只是一个建议,您的 PDF 签名不会因具有两个签名时间值而无效。但由于值不同,这可能会导致不同验证者使用一个值或另一个值产生不同的验证结果。
因此,解决此问题的另一种方法是确保根本没有将签名时间值添加到签名值字典中。这还使您签名的 PDF 跟随上面的建议,所以更准确。
不幸的是,使用PdfSignatureAppearance 方法setSignDate 设置null 值不起作用,稍后在签名过程中会导致NullPointerException 出现。但是,如果您在签名代码中使用自定义的ExternalSignatureContainer 实现(而不是ExternalSignature 实现),您可以在modifySigningDictionary 实现中删除该条目。密钥是PdfName.M。
顺便说一句,由于您的签名证书仅在半小时内有效,如果他们的验证策略只信任数字时间戳,而不是不安全的日期时间值,验证者也可能会拒绝它。
因此,您应该在证书的生命周期内添加吊销信息并为整个构造添加数字时间戳,以确保长期验证。