ITextSharp Bug? - 标记受保护的pdf时的空引用

时间:2015-01-12 08:18:27

标签: c# itextsharp

我正在使用ITextSharp's PdfStamper填写pdf表格。

这适用于不受保护且受密码保护的Pdfs,但受证书保护的PDF会在调用null reference exception时导致PdfStamper.Close()

以前有人遇到过这个吗?

示例失败的程序:

using System.Security.Cryptography.X509Certificates;
using iTextSharp.text;
using iTextSharp.text.pdf;
using System.IO;
using Org.BouncyCastle.Crypto;
using X509Certificate = Org.BouncyCastle.X509.X509Certificate;

namespace ITextError
{
    class Program
    {
        static X509Certificate2 certificate = new X509Certificate2(@"certificate.pfx","password",X509KeyStorageFlags.Exportable);
        static X509Certificate bouncyCertficate = Org.BouncyCastle.Security.DotNetUtilities.FromX509Certificate(certificate);
        static AsymmetricCipherKeyPair keyPair = Org.BouncyCastle.Security.DotNetUtilities.GetKeyPair(certificate.PrivateKey);

        public static byte[] CreatePdf()
        {
            using (MemoryStream ms = new MemoryStream())
            {
                using (Document document = new Document())
                {
                    var writer=PdfWriter.GetInstance(document, ms);
                    writer.SetEncryption(new X509Certificate[]{bouncyCertficate},
                                         new int[]{PdfWriter.ALLOW_MODIFY_CONTENTS},
                                         PdfWriter.STANDARD_ENCRYPTION_128
                                         ); 

                    document.Open();
                    document.Add(new Paragraph("Hello World"));
                }
                return ms.ToArray();
            }
        }

        public static byte[] StampPdf(byte[] src)
        {
            File.WriteAllBytes("tmp.pdf",src);
            PdfReader reader = new PdfReader("tmp.pdf",bouncyCertficate,keyPair.Private);
            using (MemoryStream ms = new MemoryStream())
            {
                using (PdfStamper stamper = new PdfStamper(reader, ms,reader.PdfVersion,true))
                {
                    PdfContentByte canvas = stamper.GetOverContent(1);
                    ColumnText.ShowTextAligned(canvas, Element.ALIGN_LEFT, new Phrase("Hello people!"), 36, 540, 0);
                    stamper.Close();
                }
                return ms.ToArray();
            }
        }  

        static void Main(string[] args)
        {
            File.WriteAllBytes(@"output.pdf",StampPdf(CreatePdf()));
        }
    }
}

异常堆栈跟踪:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
at iTextSharp.text.pdf.PdfEncryption.CreateInfoId(Byte[] id, Boolean modified)
at iTextSharp.text.pdf.PdfEncryption.GetFileID(Boolean modified)
at iTextSharp.text.pdf.PdfStamperImp.Close(PdfIndirectReference info, Int32 s kipInfo)
at iTextSharp.text.pdf.PdfStamperImp.Close(IDictionary`2 moreInfo)
at iTextSharp.text.pdf.PdfStamper.Close()
at ITextError.Program.StampPdf(Byte[] src) in Program.cs:line 45
at ITextError.Program.Main(String[] args) in Program.cs:line 53

只有在追加模式下打开压模时才会抛出异常。 但是,不使用追加模式会删除我需要保留的原始保护。

ITextSharp是Nuget stable的5.5.4版本。

1 个答案:

答案 0 :(得分:0)

此iText问题已在5.5.12版本中解决。

相关的git签入日期为2017年3月31日的d9aede3,其注释为“在对使用证书加密的文档进行签名时修复异常。由https://github.com/MADzO建议”。这种“签名”实际上是在保持证书保护完整的情况下任意盖章的特殊情况。

解决方法是在证书加密的情况下也不仅在像以前那样进行密码加密的情况下,将装入的PDF的原始文档ID添加到PdfEncryption对象(该对象包含与加密有关的信息)。

PdfEncryption类期望将其documentID成员设置为加密文档必须具有ID。由于该案件中未设置该成员,因此发生了NullReferenceException


使用当前的iTextSharp 5.5.14-SNAPSHOT开发版本进行了测试。通过撤消和重做上述修复程序进行验证。

已使用用户test data在其问题JC1001的评论中提供的iTextSharp object reference error on PdfStamper for certificate-protected file进行了测试。