iText:离线PAdES验证失败,尽管DSS已打上时间戳

编程语言 2026-07-09

下面这段代码尝试在离线模式下,使用iText的签名验证器对PDF进行验证。

复现归档包含:

  • timestamped.pdf
  • SwissSignRootCA.cer
  • SwissSignTARootCA.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几乎不需要你的时间戳,因此对你来说也不一定有利。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章