Closed pvandenbroucke closed 5 years ago
This is the code in question: https://github.com/LibrePDF/OpenPDF/blame/6ec02b3146efaac47d9a4b801b1af9dcd510cc9e/openpdf/src/main/java/com/lowagie/text/pdf/AcroFields.java#L2080
It was part of the original iText version we forked from. I have no idea why it is like this.
Can you perhaps please submit a pull-request to fix this? Perhaps create a fix, and introduce a way to keep compatibility for users who depend upon the old version of this code.
Thanks for your feedback.
Does anyone know what should be the usage of the given method ?
I also found the same method in the iText 7 Community.
We use this method quite intensively to detect whether a signature form field is signed or not. What does it do (implementation wise)?
Create a list of signed signatures. The following dictionaries are checked for their existance:
Create a list of unsigned signatures and iterate over all fields. Then add all fields which are of type signature but not in the list of step 1 and return it
So this method (should) return "signature-test" in your case but not "Signature1". You get "Signature1" when you call getSignatureNames
.
But the overall question is: Where is the problem? The method does exactly what it should. Why do you want to change it? Or do you have a bug? Or is it just to understand the concept?
@Lonzak Thanks. Which version of OpenPDF are you using? Do you have any feedback on the latest version or requests for future versions?
Hello Lonzak,
Thanks for your reply. I tried to reproduce the same behavior that I have with PDFBox following this issue : https://ec.europa.eu/cefdigital/tracker/browse/DSS-1543.
I get some difficulties with this attached file and its extensions to retrieve not signed signature fields : unsignedPDFWithSignatureFieldButInvisible.pdf.
The method getBlankSignatureNames didn't return the expected result and I needed to change that in DSS. I wanted to be sure to understand the code and its result.
We currently use the version 1.2.5.
@andreasrosdal We want to use the most current version but I didn't have the time yet to merge all our fixes of our branch into OpenPDF. This is yet on my TODO list....
@pvandenbroucke The PDF world is a small place :-) Your name sounded familiar to me and I checked my mails and we were in contact in 2017 (june) regarding some refactorings in the PAdES DSS...funny to meet here again :-)
Ok now to your PDF - the method doesn't care about its flags - so even if it is invisible it is returned since it is not signed. So looks fine to me. Or what (other) result do you expect? If I call that method I get the name back: Signature1
Signaturefield Name: Signature1 required=false is readOnly=false is hidden=true PageNumber: 1 coordinates: (x,y)=216.395,680.061 & (x,y)=366.395,712.061
But let me checked if this is a bugfix I did...
Update: I did check it: It seems not that I changed/fixed that method. So with iText 2.1.7. I get the expected result
I hope you get it prioritized, as that would help this project.
@Lonzak, yes I remember your contributions. Long time no see :-)
The problem that I have is when I sign using the existing signature field. The method still return the field as blank on the signed document. In DSS, I retrieve the empty signature field and try to fill it.
I reproduced the same code than with a visible signature field. Do I miss anything ?
Ah ok, so the problem ist not the method itself in combination with the above pdf (because that is working). In your case you take the above PDF, sign it with DSS and then openPDF still returns the field as a blank signature? Is that what you experience? If that is the case I would need to see the signed PDF for analysis...
Yes, here you have the result of the same process :
I tried to sign the same document with PDFBox and OpenPDF (B-p-LTA using the existing field Signature1). The result with PDFBox seems correct.
When applying getBlankSignatureNames()
/ getSignatureNames()
on both documents I get the following results:
lta-pdfbox.pdf: 0 unsigned, 1 signed
lta-itext.pdf: 1 unsigned and 2 signed
Which is the same what I see in adobe when opening the signature tab. So the getBlankSignatureNames()
method is not the problem here. The problem is the signing with openPDF which did not use the existing field but added two more signature fields (Signature2 and Signature3).
So I did have a look at the itext signed document and there are multiple problems in there. I tried to show it with an image (cp. below). The signature dict (50 0 obj) contains several invalid elements and seems to contain the signature field "Signature1" again. But the actual field (30 0 obj) has not been touched. But have a look for yourself:
So the overall question is: Did you use the existing PAdES signing fuctionality (which was added recently by some guy)? Or did you implement it for yourself? Depending what you used the signing method has to be fixed...
Hello Lonzak,
Thanks for the illustration.
I did an integration of OpenPDF in DSS. I moved the common code in dss-pades and created two implementation modules (openpdf and pdfbox) which run the same unit tests.
IMHO, the problem is to reuse the existing hidden field. I'm able to retrieve the related PdfDictionary but I think I need to do some more specific operations to reuse the field.
I think my problem comes from the line (in PdfSignatureAppearance) which returns false :
boolean fieldExists = !(isInvisible() || isNewField());
I'll do some more tests
Great work - I like the idea to have an DSS openPDF integration!
Yes you are right! The "isInvisble" flag would cause not to enter the correct if(...) branch. The thing I am asking myself is whether it might be valid not being able to sign it. I checked the spec:
The annotation rectangle (Rect) in such a dictionary shall give the position of the field on its page. Signature fields that are not intended to be visible shall have an annotation rectangle that has zero height and width. Conforming readers shall treat such signatures as not visible. Conforming readers shall also treat signatures as not visible if either the Hidden bit or the NoView bit of the F entry is true. The F entry is described in Table 164, and annotation flags are described in Table 165.
So only Hidden and NoView are mentioned. The Invisible flag itself is defined as follows:
If set, do not display the annotation if it does not belong to one of the standard annotation types and no annotation handler is available. If clear, display such an unknown annotation using an appearance stream specified by its appearance dictionary, if any (see 12.5.5, “Appearance Streams”).
So one could argue that since it is invisible one is not able to sign it. However from the definition one could also say that "it does belong to the standard annotation types" so just show it... This is highly confusing as always. Unfortunately I don't have a PDF 2.0 spec yet, hopefully it does clarify that point. I think we have two possibilities:
With the commented condition isInvisible() and some changes in DSS, I'm able to generate the following basic signature using the invisible field :
But I'm not able to extend it directly to LTA (FYI, the signature timestamp is included in the CAdES object). The previous isInvisible() condition is missing if I want to add a new DocumentTimestamp layer. It fails when it tries to retrieve the field Signature2.
@pvandenbroucke Please mske sure you are using the latest version of OpenPDF. Lots of fixes recently.
@andreasrosdal I did my investigations with the current master.
Some observations:
And did in the first try the Signature2
was added by openPDF or did you add it (manually)?
Yes, I know. I only uploaded the baseline profile B.
Here, you have the LT with the DSS dictionary (created and injected by the DSS framework) :
The LTA requires a new invisible signature with its Filter/SubFilter. The Signature2
name has been generated by OpenPDF. With the modified above condition, the code execute the wrong condition branch.
Closing this now. Please submit a new issue if there are further questions.
Hello,
Could you explain the implementation of the method getBlankSignatureNames ? I maybe misunderstand the goal of the method.
IMHO, we should check if the /V refer a Dictionary with the signature :
Here, the signature has been added (not blank) :
Here, we have an empty visible signature field :
Thanks in advance for your reply,
Pierrick