Certain documents with shared objects/streams gets the modified page blank after signing
Describe the bug For certain documents putting a visible signature in a page which has a /Contents with an array where one or more of the objects within it has the same number as an object in an other page causes the page with the visible signature to be blank. (Additionally if signed more then once, all but the last signature will show up as invalid in Acrobat.)
To Reproduce Code to reproduce the issue
- Sample Code
try (PdfReader reader = new PdfReader("pdflib-duplicated-out.pdf");
FileInputStream ksIn = new FileInputStream("dss10_keystore.p12")) {
Security.addProvider(new BouncyCastleProvider());
KeyStore ks = KeyStore.getInstance("pkcs12", "BC");
ks.load(ksIn, "foo123".toCharArray());
PrivateKey key = (PrivateKey) ks.getKey("signer00003", null);
Certificate[] chain = ks.getCertificateChain("signer00003");
FileOutputStream fout = new FileOutputStream(new File("target", "pdflib-duplicated-out-signed1.pdf"));
PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0', new File("/tmp"), true);
PdfSignatureAppearance sap = stp.getSignatureAppearance();
sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
// Make a modification so the page will be rewritten as it does not happen for this file otherwise for unclear resons
stp.getUnderContent(2).rectangle(1, 1, 100, 100);
sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 2, null);
stp.close();
}
Full project is available here: https://github.com/netmackan/openpdf-eliminatestreams-issue
Expected behavior Adding a digital signature to a PDF should not make the page with the visible signature blank. Also it should be possible to sign the same PDF multiple times without the verifier to complain about the previous revisions to have been modified.
Screenshots
This screenshot shows the PDF after being signed. Normally all three pages should look similar but now page 2 is blank:

System (please complete the following information):
- OS: Linux. Verifying on Windows.
- Used Font: No special
Additional context From debugging it can be seen that in the and of reading the PDF in the PdfReader class there is a method call eliminateSharedStreams() that seems to be causing this. Removing that call and the PDF seems to look correct and any further digital signatures verifies correctly in Acrobat.
PDF tools like iText RUPS shows a null entry in the array after signing and pdfcpu complains about "nil" objects. However, looking closer with the debugger shows that the shared references in the array are being replaced with new object numbers, however those objects are not added to the new PDF.
Fork with the eliminateSharedStreams() call commented out: https://github.com/LibrePDF/OpenPDF/compare/master...netmackan:no-eliminate-shared-streams-2
I have 4 different files with this issue created/modified using either QuarkExpress or pdf-lib.js. Unfortunately, those can not be shared however. I have managed to reproduce the issue with a public file which is available here (as part of the sample code): https://github.com/netmackan/openpdf-eliminatestreams-issue/blob/main/EliminateSharedStreamsIssue/pdflib-duplicated-out.pdf
It turns out that the digital signature is not needed to reproduce the issue. The following simplified sample code is enough and also gives the blank page 2:
To Reproduce
- Sample Code
try (PdfReader reader = new PdfReader("pdflib-duplicated-out.pdf")) {
FileOutputStream fout = new FileOutputStream(new File("target", "pdflib-duplicated-out-modified1.pdf"));
PdfStamper stp = new PdfStamper(reader, fout, '\0', true);
// Make a modification to page 2
stp.getOverContent(2).rectangle(1, 1, 100, 100);
stp.close();
}
Basically all that is needed is to make a modification with PdfStamper in append mode.
Anyone having an idea about what could be the issue here? Or some background on the purpose of the PdfReader.eliminateSharedStreams method?
I believe this call to eliminateSharedStream() should not be made from the readPdf() method called from the constructor of PdfReader. Instead this (public) method could be called explicitly if anyone needs it.
An other major PDF library does not have this issue and is not calling that method.
https://github.com/LibrePDF/OpenPDF/blob/8e941dc00114a5addf4e65adf11ec05eecaf15b3/openpdf/src/main/java/com/lowagie/text/pdf/PdfReader.java#L628