Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Logic behind the method AcroFields.getBlankSignatureNames() #129

Closed
pvandenbroucke opened this issue Dec 7, 2018 · 20 comments
Closed

Logic behind the method AcroFields.getBlankSignatureNames() #129

pvandenbroucke opened this issue Dec 7, 2018 · 20 comments
Labels

Comments

@pvandenbroucke
Copy link
Contributor

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) :

41 0 obj
<<
/FT /Sig
/Type /Annot
/Subtype /Widget
/F 132
/T (Signature1)
/V 42 0 R
/P 1 0 R
/Rect [0.0 0.0 0.0 0.0]
>>
endobj
42 0 obj
<<
/Type /Sig
/Filter /Adobe.PPKLite
/SubFilter /ETSI.CAdES.detached
/Name (good-user 2929c4af08f7512fe4d0290e179a9bd185abccf7)
/M (D:20181207110932+01'00')
/Contents <308214C606...0>
/ByteRange [0 137385 156331 390]               
>>
endobj

Here, we have an empty visible signature field :

8 0 obj
<<
/FT /Sig
/Type /Annot
/Subtype /Widget
/F 132
/T (signature-test)
/Rect [50.0 500.0 250.0 700.0]
/P 3 0 R
>>
endobj

Thanks in advance for your reply,

Pierrick

@andreasrosdal

This comment has been minimized.

@pvandenbroucke
Copy link
Contributor Author

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.

@Lonzak
Copy link
Contributor

Lonzak commented Dec 7, 2018

We use this method quite intensively to detect whether a signature form field is signed or not.
What does it do (implementation wise)?

  1. Create a list of signed signatures. The following dictionaries are checked for their existance:
  • Type (/FT) of the field must be /Sig
  • SignatureDictionary (/V) must be filled
  • The signature value (/Contents)
  • The ByteRange (/ByteRange)
  1. 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?

@andreasrosdal

This comment has been minimized.

@pvandenbroucke
Copy link
Contributor Author

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.

@Lonzak
Copy link
Contributor

Lonzak commented Dec 7, 2018

@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....

@Lonzak
Copy link
Contributor

Lonzak commented Dec 7, 2018

@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

@andreasrosdal

This comment has been minimized.

@pvandenbroucke
Copy link
Contributor Author

@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 ?

@Lonzak
Copy link
Contributor

Lonzak commented Dec 10, 2018

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...

@pvandenbroucke
Copy link
Contributor Author

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.

@Lonzak
Copy link
Contributor

Lonzak commented Dec 12, 2018

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:

imagesignature

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...

@pvandenbroucke
Copy link
Contributor Author

pvandenbroucke commented Dec 12, 2018

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

@Lonzak
Copy link
Contributor

Lonzak commented Dec 12, 2018

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:

  1. Patch openPDF and remove the "isInvisible()"
  2. if an invisble signature is encountered one should not be able to sign it. (With Adobe I can't click the field since it is not visible. But I can sign it via the signature tab on the left side...)

@pvandenbroucke
Copy link
Contributor Author

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.

@andreasrosdal

This comment has been minimized.

@pvandenbroucke
Copy link
Contributor Author

@andreasrosdal I did my investigations with the current master.

@Lonzak
Copy link
Contributor

Lonzak commented Dec 13, 2018

Some observations:

  • the DSS dictionary (document security store) and /VRI dict (valdiation releated information) is missing I doubt that those are already supported by openPDF

And did in the first try the Signature2 was added by openPDF or did you add it (manually)?

@pvandenbroucke
Copy link
Contributor Author

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.

@andreasrosdal
Copy link
Contributor

Closing this now. Please submit a new issue if there are further questions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants