【问题标题】:iTextsharp with signed file带有签名文件的 iTextsharp
【发布时间】:2019-08-17 20:25:08
【问题描述】:

我对 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, '\0', 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);
        }

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

【问题讨论】:

  • 你说 "created with Life Cycle" - 表单可能是 xfa 还是混合表单? Itext 仅对 xfa 表单的支持有限,正确处理已签名的表单可能超出此范围。
  • 您好 mkl,我不知道它是 xfa 还是 hybrid,因为表格来自联邦税务局。我做了两项测试,其中一项使用 C# iTextSharp,另一项使用 Java 代码。在 C# 中,语句 form.SetField 打破了前两个签名,但在 Java 中,第二个签名保持完美。第一个符号被破坏,因为(我不知道为什么)当该字段具有原始形式时,一个日期字段出现为零。
  • 啊,听起来很有趣。我将在本周晚些时候对此进行调查。
  • 非常感谢 mkl,非常感谢您的帮助
  • 话虽如此,你能分享有问题的 pdf 进行测试吗?

标签: itext


【解决方案1】:

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

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

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

为什么第一个签名被破坏了?

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

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

因此,由于四个 FECHA_*Leyenda* 字段的更改,第一个签名显示为损坏。

确实,正如您自己所说,日期字段已清除。如果您仔细查看 Leyanda 值,您会发现不同之处。

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

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

首先,比较签名前后的 XFA 表单 XML,可以看到唯一的变化(超过等效的 XML 序列化)确实是 ConsejoSubForm.OBLEA 的值。特别是,声明更改的其他四个字段在 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 规范中的规定,并且不包含专有扩展。

【讨论】:

  • mkl,您进行了出色的分析,感谢您为此付出的时间。非常感谢你,我再次说你的工作非常出色
  • 谢谢。在这种情况下,您可能希望接受答案,即通过单击投票箭头下方左上角的勾号将其标记为已接受。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多