iText:离线PAdES验证失败,尽管DSS已打上时间戳
下面这段代码尝试在离线模式下,使用iText的签名验证器对PDF进行验证。
复现归档包含:
timestamped.pdfSwissSignRootCA.cerSwissSignTARootCA.cer
复现文件: link
var stream = new FileStream("timestamped.pdf", FileMode.Open);
var ltvDocument = new PdfDocument(new PdfReader(stream));
var signatureUtil = new SignatureUtil(ltvDocument);
var certificateParser = new X509CertificateParser();
var rootCAs = new List<IX509Certificate>();
foreach (var rootCaPath in new List<string>() { "SwissSignRootCA.cer", "SwissSignTARootCA.cer"})
{
using var s2 = new FileStream(rootCaPath, FileMode.Open, FileAccess.Read);
var cert = certificateParser.ReadCertificate(s2);
Debug.Assert(cert != null);
rootCAs.Add(new X509CertificateBC(cert));
}
var validationProperties = new SignatureValidationProperties();
validationProperties.SetRevocationOnlineFetching(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts.All(),
SignatureValidationProperties.OnlineFetching.NEVER_FETCH);
var validator = new ValidatorChainBuilder()
.WithTrustedCertificates(rootCAs)
.WithSignatureValidationProperties(validationProperties)
.WithAdESReportAggregator(new DefaultAdESReportAggregator())
.BuildSignatureValidator(ltvDocument);
var validationReport = validator.ValidateSignatures();
var failures = validationReport.GetFailures();
foreach (var f in failures)
{
Console.WriteLine($"{f.GetMessage()} : {f.GetExceptionCause()?.Message}");
}
当我用timestamped.pdf运行时,出现以下失败:
Certificate revocation status cannot be checked: no revocation data available or the status cannot be determined. :
Certificate revocation status cannot be checked: no revocation data available or the status cannot be determined. :
如果允许进行在线验证,而非使用OnlineFetching.NEVER_FETCH,相同的PDF将通过验证,没有失败。
也许这是预期的行为,但我本来希望离线验证能够成功,因为:
- 该PDF包含带有OCSP与 CRL数据的DSS验证材料。
- 包含DSS的版本受到了后续文档时间戳的覆盖。
- 该后续文档时间戳可以使用提供的根CA证书进行验证。
- 嵌入的OCSP/CRL对象截至今天已过期,但在后来的文档时间戳时它们仍然有效。
我对PAdES-LTA/PAdES-DTS-A风格验证的理解是,后续的文档时间戳应当为嵌入的验证材料提供存在性证明。因此OCSP/CRL数据在进行实际验证时不应仍然需要是最新的。
环境:.NET:net10.0,iText:9.6.0,itext.bouncy-castle-adapter:9.6.0
解决方案
为对 @Glenner的回答 进一步阐释……
在验证PDF的最外层时间戳 / 签名时,我们并不知道它是在何时创建的。(是的,如果它是时间戳,它指示的是过去某个时刻,但在成功验证该时间戳之前,我们不能信任它所指示的时间。)因此,我们必须假设时间戳 / 签名可能刚刚被创建。因此,需要的吊销信息应相对较新。
在你的情形中,因此在验证那个较晚、最外层的时间戳时,我们是以当前时间进行验证。并且因为
嵌入的OCSP/CRL对象截至今天已过期,但在后来的文档时间戳时它们仍然有效。
这些嵌入的CRL/OCSP响应因此不能被使用。
实际上这也涉及到所采用的验证策略问题。iText的验证实现是按照eIDAS规定和ETSI规范来执行,在这方面相当严格。
不过如果你恰好使用Adobe Acrobat进行验证,很可能它会如你最初所设想的那样,快乐地使用旧的撤销数据。
原因在于Acrobat现在对声称的时间戳信任度较高。因此Acrobat的验证策略可能更符合你的口味。另一方面,这也意味着Acrobat几乎不需要你的时间戳,因此对你来说也不一定有利。