java中的PDF数字签名和c#中的签名验证(iText)



我正在用c#开发一个web服务器,它执行数字签名验证,以确保pdf文件没有被修改。我使用的是iText和iTextSharp。

但是客户端是基于java applet。我在java applet中执行数字签名。在java中,我可以制作签名,然后验证它们。但是如果我在c#中验证签名,它会给出一个nullreferenceexception。

这是我的Java数字签名代码:

           String path = "C:/Users/a/Desktop/cert.pfx";
    String keystore_password = "fgf";
    String key_password = "fgf";
    ////
    BouncyCastleProvider provider = new BouncyCastleProvider();
    Security.addProvider(provider);

    KeyStore ks = KeyStore.getInstance("pkcs12", "BC");
    ks.load(new FileInputStream(path), keystore_password.toCharArray());
    String alias = (String)ks.aliases().nextElement();
    PrivateKey pk = (PrivateKey) ks.getKey(alias, key_password.toCharArray());
    Certificate[] chain = ks.getCertificateChain(alias);
            PdfReader reader = new PdfReader(src);
    dest = "C:/Users/a/Desktop/" + dest;
    FileOutputStream os = new FileOutputStream(dest);
    PdfStamper stamper = PdfStamper.createSignature(reader, os, '');
    PdfSignatureAppearance appearance = stamper.getSignatureAppearance();

    ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "BC");
    ExternalDigest digest = new BouncyCastleDigest();
    MakeSignature.signDetached(appearance, digest, es, chain, null, null, null, 0, CryptoStandard.CMS);

和c#验证码:

             PdfReader reader = new PdfReader(pdfFile);
            AcroFields af = reader.AcroFields;
            var names = af.GetSignatureNames();
            if (names.Count == 0)
            {
                throw new InvalidOperationException("No Signature present in pdf file.");
            }

            foreach (string name in names)
            {
                if (!af.SignatureCoversWholeDocument(name))
                {
                    throw new InvalidOperationException(string.Format("The signature: {0} does not covers the whole document.", name));
                }

                PdfPKCS7 pk = af.VerifySignature(name);
                var cal = pk.SignDate;
                var pkc = pk.Certificates;
                if (!pk.Verify())
                {
                    Console.WriteLine("The signature is not valid.");
                    return false;
                }
             }

在af.VerifySignature(name);抛出NullReferenceException !

有趣的是,如果我用c#代码执行签名,我可以在java中验证它,因为我添加了这些指令:BouncyCastleProvider provider = new BouncyCastleProvider(); Security.addProvider(供应商);

我认为我的问题依赖于一些字节转换…但是在c#中,我不知道如何调用bouncycastleprovider。

你能帮我吗?我最诚挚的问候:William。

OP在注释中发布的堆栈跟踪

...
at org.bouncycastle.security.SignerUtil.getSigner(String algorithm)
at iTextSharp.text.pdf.PdfPKCS7..ctor(Byte[] contentsKey)
at iTextSharp.text.pdf.AcroFields.VerifySignature(String name)
at SignatureLibrary.iText.PDFValidation(String pdfFile)
in ...\SignatureLibrary\SignatureLibrary\iText.cs:line 122

包含iTextSharp.text.pdf.PdfPKCS7..ctor(Byte[] contentsKey)行,这表明OP使用的不是当前的iTextSharp 5.5.0版本,而是5.3.0之前的版本(发布于2012年6月):在5.3.0版本中,PdfPKCS7被重构到命名空间iTextSharp.text.pdf.security中。

这次重构是整个ittext签名创建和验证代码主要更新的一部分,这次更新引入了许多新特性。

因此,OP被建议更新iTextSharp程序集,并且确实:

我下载了最新的itextsharp版本,经过验证它运行良好。

最新更新