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

时间:2014-03-14 14:31:08

标签: pdf itextsharp itext digital-signature pki

我正在c#中开发一个执行数字签名验证的网络服务器,以确保不修改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, '\0');

    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(姓名);抛出NullReferenceException!

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

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

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

1 个答案:

答案 0 :(得分:1)

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 {{1}已经重构为名称空间PdfPKCS7

此重构是整个iText签名创建和验证代码的重大更新的一部分,这一更新引入了许多新功能。

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

  

我下载了最新的itextsharp版本,并且验证效果很好。