0
votes

I would like to do multiple signature on pdf document, like in a workflow. I am using following code to sign pdf which I wrote, which works fine.

To get hash

public String getHash() {
    LOGGER.debug("PDFSigner.getHash : method invoked");
    String pdfHashValue = null;
    try {
        int contentEstimated = PDFSigner.CONTENT_ESTIMATED;//8192
        HashMap<PdfName, Integer> exc = new HashMap<>();
        exc.put(PdfName.CONTENTS, contentEstimated * 2 + 2);
        PdfSignature pdfSignature = new PdfSignature(PdfName.ADOBE_PPKLITE,
                PdfName.ADBE_PKCS7_DETACHED);
        pdfSignature.setReason(appearance.getReason());
        pdfSignature.setLocation(appearance.getLocation());
        pdfSignature.setContact(appearance.getContact());
        pdfSignature.setDate(new PdfDate(appearance.getSignDate()));
        appearance.setCryptoDictionary(pdfSignature);
        appearance.preClose(exc);
        InputStream data = appearance.getRangeStream();
        MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
        byte buf[] = new byte[contentEstimated];
        int n = 0;
        while ((n = data.read(buf, 0, contentEstimated)) > 0) {
            messageDigest.update(buf, 0, n);
        }
        byte hash[] = messageDigest.digest();
        byte[] reqBytesdata = Hex.encode(hash);
        pdfHashValue = new String(reqBytesdata, "UTF8"); 
    } catch (Exception exp) {
        LOGGER.error("PDFSigner error occured getHash", exp);
    }
    return pdfHashValue;
}

To sign document

//dSignature is the received encoded signature pkcs7 (SHA256).
//starts with MIIOWQYJKoZIhvcNAQcCo.....
    public boolean doSign(String dSignature) throws IOException, DocumentException {

        boolean pdfGenerationStatus = false;
        try {
            byte[] PKCS7Response = Base64.decode(dSignature
                    .getBytes("UTF8"));
            byte[] paddedSig = new byte[PDFSigner.CONTENT_ESTIMATED];
            System.arraycopy(PKCS7Response, 0, paddedSig, 0,
                    PKCS7Response.length);
            PdfDictionary pdfDictionary = new PdfDictionary();
            pdfDictionary.put(PdfName.CONTENTS,
                    new PdfString(paddedSig).setHexWriting(true));  
            appearance.close(pdfDictionary);
            pdfGenerationStatus = true;

        } catch (Exception exp) {
            LOGGER.error("doSign ", exp);
        }
        return pdfGenerationStatus; 

    }

And the above code works fine. My new requirement is to add multiple signature. Is there any way to reuse this code snippet for the same. I have gone through this, this and this but no luck.

Other than this what I tried is, Created blank multiple blank signature and tried to attach the signature. But It resulted in creating corrupted files. I also tried creating file using method mentioned in this link. MakeSignature.signExternalContainer Also gone through a great document Digital Signatures for PDF documents

The use-case is like

  1. Create pdf
  2. Generate doc hash
  3. send to external server
  4. external server will return a pkcs7 base64 encoded string
  5. append the signature to the pdf

UPDATE

code change made was for 'append mode', following code change made my code to support multisign, thanks to @Paulo Soares, @mlk

private void initAppearanceAppend(String customerName) throws IOException, DocumentException {
    System.out.println("PDFSigner.initAppearanceAppend");
    PdfReader readerpdf = new PdfReader(this.getInputPdfFilePath());
    int lastPageNumber = readerpdf.getNumberOfPages();
    this.pdfSignatureMetaData.setPageNumber(lastPageNumber);
    this.pdfSignatureMetaData.setSignerName(customerName);
    //this.pdfSignatureMetaData.setPageNumber(PDFSigner.SIGNATURE_PAGE_NUMBER);
    OutputStream fout = new FileOutputStream(this.outputPdfFilePath);
    //PdfStamper stamperpdf = PdfStamper.createSignature(readerpdf, fout, '\0'); OLD CODE WITHOUT APPEND MODE
    PdfStamper stamperpdf = PdfStamper.createSignature(readerpdf, fout, '\0', new File("E://temp"), true);

    this.appearance = stamperpdf.getSignatureAppearance();
    LOGGER.debug("PDFSigner.initAppearanceAppend : default configurations are made");
}
1
"The use-case is like ..." - what exactly keeps you from executing that use case again and again? If you know how to add one signature to a document, what exactly is the problem in adding another one?mkl
I used the above code twice and first signature got invalidated while attaching second. In the above document I am not creating a document with empty signature. I think It should be the issue. Please correct me.arjuncc
Concerning that issue you most likely merely have to follow the advice in @Paulo's answer: Use append mode. If that does not help, please share both a PDF with one and with two signatures.mkl
Thanks a lot. I will try that wayarjuncc
You are using iText 2.1.7. Please upgrade as you shouldn't use that old version in a commercial context anymore.Bruno Lowagie

1 Answers

1
votes

(You're using iText 2.1.7, aren't you? That's old and a lot of issues were solved in 5 and a lot more in 7.)

Adding more signatures is the same as adding the first signature, just use append mode. Unless the first signature is a certified one with the appropriate permissions, only the last one will show as valid but they are all valid, just extract a revision to check.