Summary: | Bad interaction between appearance-stream generation and digital signatures | ||
---|---|---|---|
Product: | MuPDF | Reporter: | Paul Gardiner <paul.gardiner> |
Component: | mupdf | Assignee: | Sebastian Rasmussen <sebastian.rasmussen> |
Status: | UNCONFIRMED --- | ||
Severity: | normal | CC: | sebastian.rasmussen |
Priority: | P2 | ||
Version: | master | ||
Hardware: | PC | ||
OS: | Windows 10 | ||
Customer: | Word Size: | --- | |
Attachments: |
Test file with missing appearance stream
Missing appearance signed by Adobe Missing appearance signed by MuPDF Test file with non-matching appearance stream Non-matching appearance stream signed by Adobe Non-matching appearance stream signed by MuPDF Tabulated results |
Created attachment 20770 [details]
Missing appearance signed by Adobe
Created attachment 20771 [details]
Missing appearance signed by MuPDF
Created attachment 20772 [details]
Test file with non-matching appearance stream
Created attachment 20773 [details]
Non-matching appearance stream signed by Adobe
Created attachment 20774 [details]
Non-matching appearance stream signed by MuPDF
Created attachment 20775 [details]
Tabulated results
> After the file is signed by MuPDF, the file looks different under Adobe
> and MuPDF: since the field is locked by the signature, Adobe choses no
> longer to generate an appearance stream for it and so displays the field
> blank; MuPDF, on the other hand, continues to generate an appearance
> stream and displays "300".
Not entirely true. When I open TestFormExpensesMissingAppearanceSignedMuPDF.pdf
with mupdf-gl the field is rendered as "£ 300.00". Adobe does indeed
display the field as blank, but only until I click the field to edit it,
at which point "300" is displayed and a text cursor is placed at the
clicked position. I do agree that there is a difference on inital render though!
When MuPDF generated the appearance stream from the value for the field
it will also process the additional action /AA/F which calls
AFNumber_Format(2, 0, 0, 0, "\\u00a3 ", true); to format the value with
2 decimals with decimal point and have "£ " prepended to the value. It is
worth noting that processing /AA/F is entirely ignored by Adobe.
After quite some tinkering I'm not quite sure of Adobe's behaviour. Read-only marked annotations always get their appearances regenerated. This appears to be per spec. Text field widgets do get their appearances regenerated if their corresponding signature field is not signed. This seems reasonable. Text field widgets that were locked by a signed signature fielddo not get their apperances regenerated. This corresponds to what Paul has mentioned. Text field widgets that were NOT locked by a signed signature field ALSO do not get their apperances regenerated. This makes no me uncertain about what fields are actually affected by a signed signature field. Are all fields in the entire document affected? Only the ones on the same page? It doesn't appear to be _only_ those being locked by the signed signature field, so...? |
Created attachment 20769 [details] Test file with missing appearance stream There are several issues relating to this topic, but first to describe the most problematic case. TestFormExpensesMissingAppearance.pdf is a file that has one field filled in with the value "300" but with no appearance stream. The filled in field will be locked by the first signature in the file, once signed. Initially the file looks sufficiently similar under both Adobe and MuPDF: both generate the missing appearance stream for the field. After the file is signed by MuPDF, the file looks different under Adobe and MuPDF: since the field is locked by the signature, Adobe choses no longer to generate an appearance stream for it and so displays the field blank; MuPDF, on the other hand, continues to generate an appearance stream and displays "300". No such problem occurs when signing with Adobe because it adds the field's appearance stream to the file as part of signing, so that the field displays as "300" on both viewers. (I haven't established whether it does this for all fields or just for those locked by the signature). The less problematic case occurs with the file TestFormExpensesWrongAppearance.pdf. This has as field whole value is "300", but with an appearance that displays "30". Adobe and MuPDF display this differently in it's unsigned form. Adobe choses to regenerate the appearance stream, showing "300". MuPDF generates only missing appearance streams, and so shows "30". Signing this file with either system fixes the file in one of the two forms, making it, thereafter, display the same on both viewers, but which form is chosen depends on which system signs. If signing with MuPDF, the appearance stream is not updated, so continues to display as "30". Adobe also shows "30" because it respects the appearance streams of locked fields and doesn't regenerate. On the other hand, signing with Adobe causes an updated appearance stream to be committed to the file and hence the field displays, thereafter, as "300" in both viewers. The two test files plus the results of signing each under the two systems are included as attachments. Also Results.xlsx tabulates the resulting appearance of the field. The changes we may need to make to better match Adobe: 1. Not generate appearance streams for fields that are locked. 2. When signing add any generated appearance streams to the file, protected under the signature. Possibly that is necessary only for fields locked by the signature. 3. Generate appearance streams for all non-locked fields on opening a document. I think only 1. and 2. are necessary so as to protect against first mentioned problem. I believe 3. is needed for the second, but is problematic because there are cases where the appearance streams we generate are imperfect. This is the result of only a short period of analysis. There may be other problems. A bad aspect of this type of problem is that they don't become apparent in normal use. It is only when specifically attacking the security of signatures that they show up. Another attack I haven't analysed is adding an incremental change to a file that updates only the appearance stream, and not the value, of a locked field. Nor have I looked at placing one signature over another to hide the first. It's worth noting that in analysing these problems, we don't have to consider what is possible by signing or verifying with an altered version of MuPDF. Altered versions of MuPDF are useful for creating maliciously prepared files, but should not be used for either signing or verification. We don't have to consider this possibility because part of protecting one's private key is not to use it other than with known good software.