0

I have a problem with PDF signed. I received a PDF file, created with Life Cycle (Acrobat) that already contain two digital signing over some acroFields. I have to put a couple of data over other acrofields, and I´m using the follow code in 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);
        }

The problem is the new file has the two previous signing broken. I don´t know what is wrong. Thanks in advance

walterB
  • 11
  • 4
  • You say *"created with Life Cycle"* - is the form probably a xfa or hybrid form? Itext only has limited support for xfa forms, and properly handling signed ones might be beyond that. – mkl Aug 14 '19 at 05:39
  • Hello mkl, I don´t know if it is xfa or hybrid, because the form come from the Federal Tax Agency. I did two test, one of them with C# iTextSharp and other with Java code. In C# the sentence form.SetField break the two previous signing, but with Java the second sign remain perfect. First sign is broken because (I don´t know why) one date field appear in zero when this field has a valor into original form. – walterB Aug 14 '19 at 12:13
  • Ah, that sounds interesting. I'll look into that later this week. – mkl Aug 14 '19 at 16:30
  • thanks a lot mkl, I appreciate your help very much – walterB Aug 14 '19 at 17:42
  • That being said, can you share the pdf in question for testing? – mkl Aug 14 '19 at 19:05
  • The PDF file is here: https://1drv.ms/b/s!AnggmeMAJPFggYRnU5nSWmKCc8qbkA?e=LvoWe9 – walterB Aug 14 '19 at 20:42
  • *"In C# the sentence form.SetField break the two previous signing, but with Java the second sign remain perfect."* - I just tested it, but here in both cases the second signature remains valid (or as valid as can be without trust). Which iText/Java and iTextShatp/.Net versions do you use? – mkl Aug 15 '19 at 16:54
  • I'm using itextsharp 5.5.13.1 (C#) and itext 5.3.5 (java). The Framework .Net is 4.5 and for Java I use NetBeans IDE 8.2. My profile is developer .Net, but somethings I have to develop in Java. The other question is why the first signature is broken, I don´t understand, except because in the out PDF a couple of Dates ("Fecha de cierre" and "Fecha de Realizacion") both are in blanks, when they have data in the original PDF. – walterB Aug 15 '19 at 17:25
  • Actually iText 5.3.5 in Java is really old, I would have expected an issue more likely here. – mkl Aug 16 '19 at 08:36
  • so, what do you think that it can be happening here ? – walterB Aug 16 '19 at 12:20

1 Answers1

0

Taking the comments to the question into consideration, you observed your iTextSharp/C# code break both previous signatures and your iText/Java code break only the first one. So there are two topics of interest here:

  • Why is there a different outcome of C# and Java code?
  • Why are signatures broken at all?

I tried to reproduce the issue. Unfortunately, though, I got a different result, here both the C# and the Java version only break the first signature. Thus, I here try to explain why the first signature is broken.

Why is the first signature broken?

Adobe Acrobat signature properties show that the original revision of the PDF was not manipulated. Thus, some of the changes made in the incremental update added by your code are considered invalid. Acrobat lists modifications in the fields ConsejoSubForm.OBLEA, ContribuyenteSubForm.FECHA_CIERRE, ContribuyenteSubForm.FECHA_REALIZACION, ContribuyenteSubForm.LeyendaAdjuntarArchivo, and Encabezado.FECHA_ACTUAL (I dropped all the [0]s and the FORMULARIO[0].SUBFORMULARIO[0] prefix here).

Inspecting the XFA one finds that the signature field FIRMA_CONTRIBUYENTE (the field containing the first signature) disallows changes to the fields collected as camposFirmaContribuyente; of the modified fields all but ConsejoSubForm.OBLEA are in this collection.

Thus, the first signature is displayed as broken because of changes in the four FECHA_* and Leyenda* fields.

Indeed, as you have said yourself, the date fields are cleared. And if you look at the Leyanda value closely, you'll find a difference.

Why are there changes to all those fields?

The code is meant to only change the ConsejoSubForm.OBLEA field (which is not protected by the first signature) but not the four other ones. So why are they changed, too?

First of all, comparing the XFA form XMLs before and after signing, one sees that the only change (in excess of equivalent XML serialization) indeed is the value of ConsejoSubForm.OBLEA. In particular, the four other fields with claimed changes are not changed in the XFA XML!

Thus, neither did iText explicitly change fields it was not meant to change nor can those other changes be found in the XFA XML.

Why does Adobe consider them changed?

Searching for the four FECHA_* and Leyenda* field values in the XFA XML one finds that these values are not contained in the {http://www.xfa.org/schema/xfa-data/1.0/}:datasets section (which according to the XFA specification contains all the sets of data used with the form) but instead in a separate {http://www.xfa.org/schema/xfa-form/2.8/}:form section.

This section is not specified in the XFA specification 3.3.

One thing about this section that strikes the eye is that {http://www.xfa.org/schema/xfa-form/2.8/}:form element contains a checksum attribute:

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

This attribute actually is the focus of this question by Bruno Lowagie.

My interpretation of this:

  • Adobe uses this proprietary part of the XFA XML to store extra form data which are not contained in the XFA datasets.
  • Furthermore, it stores a checksum over some representation of the whole form state to determine that this proprietary part is still based on the current state of the other form data.
  • iText did not update this undocumented checksum.
  • Adobe Acrobat, therefore, upon opening the form detects that there are changes to the underlying form data not synchronized with the proprietary {http://www.xfa.org/schema/xfa-form/2.8/}:form section and re-initializes the data in this section which changes the four FECHA_* and Leyenda* field values according to the respective field definitions.
  • When validating the first signature, Adobe Reader determines that the changes due to that re-initialization are not allowed by the signature field definition and displays the signature as broken.

TL;DR

In the XFA form at hand proprietary Adobe extensions to the XFA specification were used for some form data and a form data checksum. As this extension is not publicly documented, iText could not update it appropriately. This made Adobe Acrobat consider the signature broken after iText updated the OBLEA field.

Such proprietary additions might be the reason why in PDF 2.0 XFA forms have been declared deprecated.

If you want to edit XFA forms with iText, therefore, please make sure that the form completely is as specified in the XFA specification and does not contain proprietary extensions.

Community
  • 1
  • 1
mkl
  • 90,588
  • 15
  • 125
  • 265
  • mkl, you have done a brilliant analysis, I appreciate the time you dedicated at this. Thanks you very much and I say anew excellent your job – walterB Aug 18 '19 at 17:31
  • Thanks. In that case you may want to accept the answer, i.e. mark it as accepted by clicking the tick at its upper left, underneath the voting arrows. – mkl Aug 18 '19 at 20:59