本文介绍了在itextsharp中的Pades LTV验证抛出Uri前缀未被识别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已成功签署了支持LTV的pdf。我可以通过Adobe Acrobat Reader和外部验证器检查pdf和LTV签名是否有效。

I have successfully signed a pdf with LTV support. I can check the pdf and LTV signature is valid through Adobe Acrobat Reader and also with an external validator.

我正在尝试使用iTextSharp 5.5.10进行相同的验证

I'm trying to make the same validation with iTextSharp 5.5.10.

我的追踪对象的iText示例代码

I'm following the iText sample code C5_06

但是当我打电话给 ltvVerifier.Verify 时,我我得到 System.NotSupportedException,Uri前缀无法识别。我正在加载用于签署pdf en cert参数的证书。

But when I call to ltvVerifier.Verify, I am getting a System.NotSupportedException, The Uri Prefix is not Recognized. I am loading the certificate used to sign the pdf en cert parameter.

验证码:

   public static bool Validate(byte[] pdfIn, X509Certificate2 cert)
    {
        using (var reader = new PdfReader(pdfIn))
        {
            var fields = reader.AcroFields;
            var signames = fields.GetSignatureNames();

            if (!signames.Any(n => fields.SignatureCoversWholeDocument(n)))
                throw new Exception("None signature covers all document");

            var verifications = signames.Select(n => fields.VerifySignature(n));

            var invalidSignature = verifications.Where(v => !v.Verify());
            var invalidTimeStamp = verifications.Where(v => !v.VerifyTimestampImprint());

            if (invalidSignature.Any())
                throw new Exception("Invalid signature found");
        }

        using (var reader = new PdfReader(pdfIn))
        {
            var ltvVerifier = new LtvVerifier(reader)
            {
                OnlineCheckingAllowed = false,
                CertificateOption = LtvVerification.CertificateOption.WHOLE_CHAIN,
                Certificates = GetChain(cert).ToList(),
                VerifyRootCertificate = false,
                Verifier = new MyVerifier(null)
            };

            var ltvResult = new List<VerificationOK> { };
            ltvVerifier.Verify(ltvResult);

            if (!ltvResult.Any())
                throw new Exception("Ltv verification failed");
        }
        return true;
   }

从证书链构建X509Certificates列表的辅助功能:

Auxiliary function that builds a List of X509Certificates from the certificate chain:

    private static X509.X509Certificate[] GetChain(X509Certificate2 myCert)
    {
        var x509Chain = new X509Chain();
        x509Chain.Build(myCert);

        var chain = new List<X509.X509Certificate>();
        foreach(var cert in x509Chain.ChainElements)
        {
            chain.Add(
                DotNetUtilities.FromX509Certificate(cert.Certificate)
                );
        }

        return chain.ToArray();
    }

自定义验证程序,仅从样本中复制:

A custom verifier, just copied from sample:

 class MyVerifier : CertificateVerifier
{
    public MyVerifier(CertificateVerifier verifier) : base(verifier) { }

    override public List<VerificationOK> Verify(
        X509.X509Certificate signCert, X509.X509Certificate issuerCert, DateTime signDate)
    {
        Console.WriteLine(signCert.SubjectDN + ": ALL VERIFICATIONS DONE");
        return new List<VerificationOK>();
    }
}

这是相关的堆栈跟踪:


And this is the relevant stack trace:

  in System.Net.WebRequest.Create(Uri requestUri, Boolean useUriBase)
   in System.Net.WebRequest.Create(String requestUriString)
   in iTextSharp.text.pdf.security.CrlVerifier.GetCrl(X509Certificate signCert, X509Certificate issuerCert)
   in iTextSharp.text.pdf.security.CrlVerifier.Verify(X509Certificate signCert, X509Certificate issuerCert, DateTime signDate)
   in iTextSharp.text.pdf.security.OcspVerifier.Verify(X509Certificate signCert, X509Certificate issuerCert, DateTime signDate)
   in iTextSharp.text.pdf.security.LtvVerifier.Verify(X509Certificate signCert, X509Certificate issuerCert, DateTime sigDate)
   in iTextSharp.text.pdf.security.LtvVerifier.VerifySignature()
   in iTextSharp.text.pdf.security.LtvVerifier.Verify(List`1 result)

谢谢。

推荐答案

T他的问题是签名者证书链中的证书为CRL下载提供了两个URI,首先是一个ldap URI,然后是一个http URI,参见。 @ Egl对您的问题的评论,但iText假设它可以简单地采用第一个给定的URI并使用 System.Net.WebRequest 来请求其内容。

The problem is that the certificates in the signer certificate chain present two URIs for CRL download, first a ldap URI and then a http URI, cf. @Egl's comment to your question, but that iText assumes it can simply take the first given URI and use System.Net.WebRequest to request its content.

不幸的是 WebRequest 开箱即用只支持http:,https:,ftp:和文件:(cf. )。因此,它无法通过ldap尝试通过带有异常的iText尝试通过ldap请求CRL。

Unfortunately WebRequest out-of-the-box only supports http:, https:, ftp:, and file: (cf. this msdn page). Thus, it fails iText's attempt to request the CRL via ldap with an Exception which iText doesn't catch.

你可以通过


  • 注册ldap WebRequest 处理程序来完成这项工作(参见)。

  • either registering a ldap WebRequest handler (cf. this msdn page).

警告:虽然msdn页面表明可以做这样的事情,但我还没有这样做。此外,OP无法轻易遵循这条道路。因此,可能存在超出msdn文档描述的限制。可能只能使用 web -ish protocols(ftp:,file:,http:,https :)?

Caveat: While the msdn pages suggest that doing something like this is possible, I have not yet done it. Furthermore the OP could not easily follow this path. Thus, there might be restrictions beyond what the msdn documentation describes. Probably only web-ish protocols (ftp:, file:, http:, https:) can be used?

或者改变iText验证器(实际上更改iText类或复制/派生自己的 CrlVerifier LtvVerifier 变体)以使用http -URI。

Or changing the iText verifiers (either actually changing iText classes or copying/deriving one's own CrlVerifier and LtvVerifier variants) to use the http-URI.

这可以通过捕获此类异常然后继续使用下一个CRL请求URI或(由OP完成)通过完全忽略ldap URI来实现(在 CertificateUtil.GetCRLURL 中过滤。)

This can either be implemented by catching such exceptions and then continuing with the next CRL request URI or (as done by the OP) by ignoring the ldap URI altogether (filtering it in CertificateUtil.GetCRLURL).

这篇关于在itextsharp中的Pades LTV验证抛出Uri前缀未被识别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-10 15:09