ITextSharp 签名 PDF/A 文档

ITextSharp signing PDF/A document

所以我正在尝试签署一份 PDF/A-1A 文档,该文档是使用 ITextSharp 生成的。当我签署文档并尝试验证文档时,出现以下错误,

Validating file "test_pdfA_compliance_signed.pdf" for conformance level pdfa-1a The required XMP property 'pdfaid:part' is missing. The required XMP property 'pdfaid:conformance' is missing. A string is longer than 65535 bytes. The document does not conform to the requested standard. The document doesn't conform to the PDF reference (missing required entries, wrong value types, etc.). The document's meta data is either missing or inconsistent or corrupt. Done.

文件预签名:https://drive.google.com/file/d/0B9RyqgJoa6W8UDFSeHJSX09QamM/view?usp=sharing

文档Post-签名:https://drive.google.com/file/d/0B9RyqgJoa6W8Y3lGbFU4a2RsLWc/view?usp=sharing

但签名过程按预期完成,但我意识到,如果我测试文档是否声称符合 PDF/A,它会失败,就好像没有元数据声称 PDF/A ,

private bool CreatePdfStamperIsPDFADocument(PdfReader reader)
    {
        if (reader.Metadata != null && reader.Metadata.Length > 0)
        {
            IXmpMeta xmpMeta = XmpMetaParser.Parse(reader.Metadata, null);
            IXmpProperty pdfaidConformance = xmpMeta.GetProperty(XmpConst.NS_PDFA_ID, "pdfaid:conformance");
            IXmpProperty pdfaidPart = xmpMeta.GetProperty(XmpConst.NS_PDFA_ID, "pdfaid:part");

            if (pdfaidConformance == null || pdfaidPart == null)
            {
                return false;
            }
        }

        return true;
    }

我用来签署文档的代码,这里使用的PDF印章是正常的,因为检查失败。当我尝试使用 PDFAStamper 时,它抱怨说只能使用 PDF/A 文档。

private byte[] SignDocument(Certificate certificate, SigningInformation information, List<SigningBlock> signingBlocks, List<MemberItemSignature> signatureImages, byte[] document, bool certify)
    {
        for (int i = 0; i < signingBlocks.Count; i++)
        {
            using (MemoryStream outputStream = new MemoryStream())
            {
                using (PdfReader reader = new PdfReader(document))
                {
                    using (PdfStamper stamper = CreatePdfStamper(reader, outputStream, true))
                    {
                        SigningBlock signingBlock = signingBlocks[i];
                        PdfSignatureAppearance appearance = CreatePdfAppearance(stamper, information, certify && i == 0);

                        SignDocumentSigningBlock(certificate, information, signingBlock, appearance, stamper, GetSignatureImage(signatureImages, signingBlock.Name));
                    }
                }

                document = outputStream.ToArray();
            }
        }

        return document;
    }

所以这是我确定要使用哪个 PDF 压模的代码,但这是它失败的地方,因为我使用的文档为我用来确定 PDF/A 声明的两个组件返回 null,

        private PdfStamper CreatePdfStamper(PdfReader reader, MemoryStream outputStream, bool isSignature)
    {
        if (isSignature)
        {
            if (CreatePdfStamperIsPDFADocument(reader))
            {
                return PdfAStamper.CreateSignature(reader, outputStream, _pdfVersion, null, true, PdfAConformanceLevel.PDF_A_1A);
            }
            else
            {
                return PdfStamper.CreateSignature(reader, outputStream, _pdfVersion, null, true);
            }
        }
        else
        {
            return new PdfStamper(reader, outputStream, _pdfVersion, true);
        }
    }

我是在做蠢事还是漏掉了什么小东西? 感谢您的帮助。

亲切的问候

使用常规 PdfStamper 时,iTextSharp 不会尝试使您的输出文件 PDF/A 兼容。特别是,它不会添加任何 PDF/A 相关的元数据。因此,预计您对已签名文档的元数据 (CreatePdfStamperIsPDFADocument()) returns false 的测试。

当 运行 输入文件中的代码示例时,它 returns truepdfaidPart 等于 1pdfaidConformance等于 A。这是调试器在 运行 代码时显示的内容:

要获得 PDF/A 输出文件,您必须使用 PdfAStamper。你说 PdfAStamper 给你一个关于你的输入文件不是 PDF/A 的错误。这可能是因为您指定了与输入文件不同的 PDF/A 部分 and/or 一致性级别。 PdfAStamper 不会将 PDF/A 输入文件转换为不同的部分或一致性级别。

因此请确保为 PDF/A-1a 输入创建 PdfAStamper

PdfStamper stamper = PdfAStamper.CreateSignature(reader, outputfile,
    '[=10=]', PdfAConformanceLevel.PDF_A_1A);