5

I am having trouble with stamping PDF documents without invalidating digital signatures.

Current, I succeeded stamping a PDF. However, if the document is previously signed the signature is no longer valid. I understand why that happens, but if I use Acrobat to add text or stamp it using annotation, the signature is valid.

I tried adding annotations or comments but it still invalidates the signature. Is there a way to add stamp to a PDF using iText without invalidating digital signatures?

Here is a snippet of the code i use to stamp:

        PdfReader reader = new PdfReader(inputstream);

        stamp = new PdfStamper(reader, new FileOutputStream(file));


        PdfContentByte pcb;
        BaseFont bf = BaseFont.createFont("Courier", BaseFont.CP1250,BaseFont.EMBEDDED);

        Rectangle r = reader.getPageSizeWithRotation(1);

        pcb = stamp.getOverContent(1);

        // set the font and size
        float size = 12;
        pcb.setFontAndSize(bf, size);

        float width = 90;
        float centerX = 0, startY = 0;
        centerX = r.getWidth() - (width / 2) - 20;
        startY = r.getHeight() - (15 * 2) - 145;

        pcb.beginText();
        pcb.showTextAligned(PdfContentByte.ALIGN_CENTER, stampText, centerX, startY, 0);

        pcb.setFontAndSize(bf, 10);
        pcb.showTextAligned(PdfContentByte.ALIGN_CENTER, date, centerX-9, startY-8, 0);
        pcb.endText();
        stamp.close();          

Any help will be much appreciated, Thanks

The Macedon
  • 199
  • 2
  • 12
  • 1
    As explained in the answer to [how to add blank page in digitally signed pdf using java?](http://stackoverflow.com/questions/16710439/how-to-add-blank-page-in-digitally-signed-pdf-using-java) you can not add content to a signed PDF the way you do. You claim that you can do this with Acrobat, but that is simply not true. You are probably confusing text in an annotation with text added to the content stream. If the signature allows adding annotations, you should add a text annotation using `PdfStamper` in *append mode*. – Bruno Lowagie May 14 '15 at 10:01
  • I was able to add content via Acrobat only through text in an annotation, I am sorry for the misunderstanding. I succeeded to add comment without invalidating the signatures. However I can't get the hang of freeTextAnnotation, it still invalidates the signatures. I'm using `stamp = new PdfStamper(reader, new FileOutputStream(file), '\0', true); PdfContentByte pcb = new PdfContentByte(stamp.getWriter()); float size = 12; pcb.setFontAndSize(bf, size); PdfAnnotation annot2 = PdfAnnotation.createFreeText(stamp.getWriter(), new Rectangle(x, y, x1, y1), "A1", pcb); stamp.addAnnotation(annot2, 1)` – The Macedon May 14 '15 at 10:47
  • @The Please add such code clarifications to the question. – mkl May 14 '15 at 11:14

1 Answers1

8

I made it happen' :)

Here is the code used to add custom text to document using iText without invalidating digital signatures.

//Read the source PDF
PdfReader reader = new PdfReader(inputstream);
//Create PdfStamp object
stamp = new PdfStamper(reader, new FileOutputStream(file), '\0', true);

//Create the proper annotation
PdfAnnotation annot = PdfAnnotation.createFreeText(stamp.getWriter(),  new Rectangle(150, 150, 200, 200), "Annotation 1", pcb);
annot.setFlags(PdfAnnotation.FLAGS_PRINT);

//Insert the annotation         
stamp.addAnnotation(annot, 1);
//Close the stamp
stamp.close();  

EDIT:

For inserting image stamp to the document without invalidating the digital signatures I used this code:

//Read the pdf 
PdfReader reader = new PdfReader(inputstream);
//Use PdfStamper in append mode
stamp = new PdfStamper(reader, new FileOutputStream(file), '\0', true); 

//Read the image
Image img = Image.getInstance(ImageIO.read(imgStream), null);

float w = img.getScaledWidth();
float h = img.getScaledHeight();
Rectangle location = new Rectangle(70, 770 - h, 70 + w, 770);

//Create stamp annotation           
PdfAnnotation stampAnnot = PdfAnnotation.createStamp(stamp.getWriter(), location, null, "ITEXT");
img.setAbsolutePosition(0, 0);
//Create new PdfContentByte from the stamp writer
//If you use cd = stamp.getOverContent(1) - you'll invalidate the signatures
PdfContentByte cb = new PdfContentByte(stamp.getWriter());
PdfAppearance app = cb.createAppearance(w, h);
app.addImage(img);
stampAnnot.setAppearance(PdfName.N, app);
stampAnnot.setFlags(PdfAnnotation.FLAGS_PRINT);

stamp.addAnnotation(stampAnnot, 1);
reader.close();
Bruno Lowagie
  • 75,994
  • 9
  • 109
  • 165
The Macedon
  • 199
  • 2
  • 12
  • 2
    Yep, now you are using `PdfStamper` in append mode. You are not changing the content stream; you are using an annotation instead. Problem solved ;-) – Bruno Lowagie May 14 '15 at 13:54
  • @BrunoLowagie I'm struggling with putting a stamp annotation containing an image. As in **Acrobat** to chose a PDF image of the stamp and insert it as annotation. By now I know that I am annoying, but I can not find an answer to this anywhere. Thank you in advance! – The Macedon May 15 '15 at 07:41
  • Did you try the [AddStamp](http://itextpdf.com/sandbox/annotations/AddStamp) example? It adds a stamp with the image of the iText logo. – Bruno Lowagie May 15 '15 at 07:57
  • Yes, I did and it adds an image stamp. However, I'm facing the same problem as before, it invalidates the signatures. The signatures allows adding annotation and I am using `PdfStamper` in append mode as well. I suppose that happens because of the `PdfContentByte`. Any suggestions? Thanks – The Macedon May 15 '15 at 08:25
  • 2
    I'd have to experiment, and I only have limited time. You'll have to (1) hope that somebody else has time, or (2) find time to experiment yourself, or (3) use paid support at iText if nobody can make time for you. – Bruno Lowagie May 15 '15 at 08:31
  • I will try my best. Thank you for everything :) – The Macedon May 15 '15 at 08:34
  • @BrunoLowagie I succeeded. The answer is in the post above. Thank you for everything. – The Macedon May 15 '15 at 08:53
  • 2
    If I could double-up-vote I would. Thanks for updating your answer. It will be useful for further reference. – Bruno Lowagie May 15 '15 at 08:58
  • @BrunoLowagie Is there a possibility to lock the PDF (set encryption) after adding annotation? I used [link](http://itextpdf.com/sandbox/security/EncryptPdfWithoutUserPassword) this example but it does not work in my case. It does not go past this line: `stamper.setEncryption(null, "World".getBytes(), PdfWriter.ALLOW_PRINTING, PdfWriter.ENCRYPTION_AES_128 | PdfWriter.DO_NOT_ENCRYPT_METADATA);` – The Macedon May 15 '15 at 12:55
  • Encrypting changes content streams, hence it will break all signatures if you encrypt *after* signing. Locking is usually not done through encrypting. You can lock a document by adding an extra signature using the correct MDP settings. In ISO-32000-1, this is only possible for the author signature (which is always the first signature). In ISO-32000-2, it will be possible to define MDP settings for approval signatures too. This is already implemented in iText. – Bruno Lowagie May 15 '15 at 13:03
  • @BrunoLowagie just one question about the first snippet of code: how is the 'pcb' object is created? Using both 'pcb = new PdfContentByte(stamp.getWriter())' and 'pcb = stamp.getOverContent(1)' is invalidating the signature in my case. At least, I guess it is caused by how the pcb object is created.. – oidualc Jun 20 '17 at 12:55
  • @oidualc Why are you using `stamp.getOverContent(1)` on a signed PDF file? **Stamping content on a page should always invalidate the signature.** – Bruno Lowagie Jun 20 '17 at 13:00
  • @BrunoLowagie ok, but what about 'pcb = new PdfContentByte(stamp.getWriter())'? This still invalidates the signature. By the way, thank you very much for your work, it's helping a lot – oidualc Jun 20 '17 at 13:17
  • @BrunoLowagie you don't have to, but it would help if you do. No assumptions needed, I'm trying to do exactly what the answer is claiming to resolve: adding an annotation that contains text to a signed pdf, without invalidating the signature. Not sure where the forge part comes from.. – oidualc Jun 20 '17 at 13:28