编程语言
首页 > 编程语言> > C#-itextsharp中的Pads LTV验证引发Uri前缀无法识别

C#-itextsharp中的Pads LTV验证引发Uri前缀无法识别

作者:互联网

我已经在LTV支持下成功签署了pdf文件.我可以通过Adobe Acrobat Reader以及外部验证器检查pdf和LTV签名是否有效.

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

我正在关注iText示例代码C5_06

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

验证码:

   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;
   }

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

    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();
    }

一个自定义验证程序,仅从示例复制而来:

 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>();
    }
}

这是相关的堆栈跟踪:

  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)

谢谢.

解决方法:

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

不幸的是,开箱即用的WebRequest仅支持http:,https:,ftp:和file :(比照this msdn page).因此,iText尝试通过ldap请求CRL的尝试失败,但iText没有捕获到异常.

您可以通过以下方式进行这项工作

>或者注册ldap WebRequest处理程序(参见this msdn page).

警告:虽然msdn页面建议可以执行类似操作,但我尚未执行此操作.此外,OP无法轻易地遵循这一路径.因此,可能存在超出msdn文档描述范围的限制.可能只能使用网络式协议(ftp:,file:,http:,https :)?
>或更改iText验证程序(实际上是更改iText类或复制/派生自己的CrlVerifier和LtvVerifier变体)以使用http-URI.

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

标签:pdf,itext,digital-signature,c
来源: https://codeday.me/bug/20191026/1936111.html