带签名文件的 iTextsharp

iTextsharp with signed file

我对 PDF 签名有疑问。我收到了一个 PDF 文件,该文件是使用 Life Cycle (Acrobat) 创建的,其中已经包含对某些 acroFields 的两个数字签名。我必须将一些数据放在其他 acrofields 上,我在 C# 中使用以下代码:

    PdfReader pdfReader = null;
        PdfStamper stamper = null;
        string filePDF = @"C:\Visual Studio Solutions\Visual Windows\cpce Certificaciones\prueba_xfa.pdf";
        string outPDF = @"C:\Visual Studio Solutions\Visual Windows\cpce Certificaciones\prueba_xfa_out.pdf";
        try
        {
            using (var inStream = new FileStream(filePDF, FileMode.Open))
            {
                pdfReader = new PdfReader(inStream);
            }

            using (var outStream = new FileStream(outPDF, FileMode.Create))
            {
                stamper = new PdfStamper(pdfReader, outStream, '[=10=]', true);

                var form = stamper.AcroFields;

                form.SetField("FORMULARIO[0].SUBFORMULARIO[0].ConsejoSubForm[0].OBLEA[0]", "probando");

                stamper.Close();
                pdfReader.Close();

            }
        }
        catch (Exception ex)
        {
            throw new Exception("error: " + ex.Message);
        }

问题是新文件破坏了之前的两个签名。 我不知道出了什么问题。 提前致谢

考虑到对问题的评论,您观察到您的 iTextSharp/C# 代码破坏了两个先前的签名,而您的 iText/Java 代码仅破坏了第一个签名。所以这里有两个感兴趣的话题:

  • 为什么 C# 和 Java 代码的结果不同?
  • 为什么签名会被破坏?

我试着重现了这个问题。不幸的是,我得到了不同的结果,这里 C# 和 Java 版本都只破坏了第一个签名。因此,我在这里尝试解释第一个签名被破坏的原因。

为什么第一个签名坏了?

Adobe Acrobat 签名属性显示 PDF 的原始修订版未被篡改。因此,您的代码添加的增量更新中所做的一些更改被认为是无效的。 Acrobat 列出了 ConsejoSubForm.OBLEAContribuyenteSubForm.FECHA_CIERREContribuyenteSubForm.FECHA_REALIZACIONContribuyenteSubForm.LeyendaAdjuntarArchivoEncabezado.FECHA_ACTUAL 字段中的修改(我删除了所有 [0]FORMULARIO[0].SUBFORMULARIO[0] 前缀)。

检查 XFA 发现签名字段 FIRMA_CONTRIBUYENTE(包含第一个签名的字段)不允许更改收集为 camposFirmaContribuyente 的字段;除 ConsejoSubForm.OBLEA 之外的所有修改字段都在此集合中。

因此,第一个签名显示为已损坏,因为四个 FECHA_*Leyenda* 字段发生了变化。

的确,正如您自己所说,日期字段已被清除。而如果你仔细观察Leyanda值,你会发现不同。

为什么所有这些字段都有变化?

该代码旨在仅更改 ConsejoSubForm.OBLEA 字段(不受第一个签名保护)而不更改其他四个字段。那为什么他们也改变了?

首先,比较签名前后的XFA表单XMLs,唯一的变化(超过等效XML序列化)确实是[=11的值=].特别是,声称更改的其他四个字段 在 XFA XML!

中未更改

因此,iText 既没有明确更改它不打算更改的字段,也无法在 XFA 中找到其他更改 XML。

为什么 Adob​​e 认为它们已更改?

在 XFA XML 中搜索四个 FECHA_*Leyenda* 字段值,发现这些值 包含在{http://www.xfa.org/schema/xfa-data/1.0/}:datasets 部分(根据 XFA 规范 包含与表单 一起使用的所有数据集)但在单独的 {http://www.xfa.org/schema/xfa-form/2.8/}:form 部分中。

XFA规范3.3中没有规定这一段

关于此部分的一件事引人注目的是 {http://www.xfa.org/schema/xfa-form/2.8/}:form 元素包含一个 checksum 属性:

<form xmlns="http://www.xfa.org/schema/xfa-form/2.8/"
    checksum="Y3ReuUF4b/rARe9AfHzXknOOs5Q=">

这个属性实际上是 Bruno Lowagie this question 的重点。

我对此的解读:

  • Adobe 使用 XFA 的这个专有部分 XML 来存储 XFA 数据集中不包含的额外表单数据。
  • 此外,它在整个表单状态的某些表示上存储校验和,以确定该专有部分仍然基于其他表单数据的当前状态。
  • iText 没有更新这个未记录的校验和。
  • 因此,Adobe Acrobat 在打开表单时会检测到基础表单数据的更改未与专有 {http://www.xfa.org/schema/xfa-form/2.8/}:form 部分同步,因此 重新初始化此部分中的数据 根据各自的字段定义更改四个 FECHA_*Leyenda* 字段值。
  • 验证第一个签名时,Adobe Reader 确定由于 重新初始化 导致的更改不被签名字段定义所允许,并将签名显示为坏了。

TL;DR

在手头的 XFA 表单中,XFA 规范的专有 Adob​​e 扩展用于某些表单数据和表单数据校验和。由于此扩展未公开记录,iText 无法对其进行适当更新。这使得 Adob​​e Acrobat 认为在 iText 更新 OBLEA 字段后签名已损坏。

此类专有添加可能是 PDF 2.0 XFA 表单被宣布弃用的原因。

因此,如果要使用 iText 编辑 XFA 表单,请确保表单完全符合 XFA 规范的规定,并且不包含专有扩展。