External Digital Signature with IText

91 views Asked by At

I have a problem with external digital signature. Im using IText 5.5.13 with java.

step 1 - preparing the pdf step 2 - calculating the hash step 3 - signing the hash step 4 - combine hash to the source pdf

Im getting error: NO FIELD

Help is much apricated

Here is My Code:

//step 1 - preparing pdf to sign

 int contentEstimated2 = 8192;
 String src = "src.pdf";
 String dest = "dest.pdf";
 InputStream is = new FileInputStream(src);
 PdfReader reader = new PdfReader(is);
 reader.setAppendable(true);
 ByteArrayOutputStream  baos = new ByteArrayOutputStream ();
 FileOutputStream os = new FileOutputStream(dest);
 PdfStamper stamper = PdfStamper.createSignature(reader, baos, '\0');
 PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
 String MotSigner = "GIF.jpg"; //IMAGE
 Image image = Image.getInstance(MotSigner);
 appearance.setImage(image);
appearance.setLayer2Text("");
Rectangle rect = new Rectangle(250, 795, 300, 840);
appearance.setVisibleSignature(rect, 1, "sig1");
ExternalSignatureContainer external = new
ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
 MakeSignature.signExternalContainer(appearance, external, size);

// step 2 - calculating the hash
  is = new ByteArrayInputStream(baos.toByteArray());
  BouncyCastleDigest digest = new BouncyCastleDigest();
  byte[] hash = DigestAlgorithms.digest(is, digest.getMessageDigest("SHA-256"));

//step 3 - signing the hash 
    //sending hash to signer server. getting SignedBytes as result
 byte[] SignHashedPDF = Base64.decode(SignedBytes);


//step 4 - combine hash to the source pdf                                   
reader = new PdfReader(src);
FileOutputStream os1 = new FileOutputStream(dest);
ExternalSignatureContainer external1 = new MyExternalSignatureContainer(SignHashedPDF);
MakeSignature.signDeferred(reader, "sig1", os1, external1);
 os.close();

}                      

 



class MyExternalSignatureContainer implements ExternalSignatureContainer {

    protected byte[] sig;

    public MyExternalSignatureContainer(byte[] sig) 
        this.sig = sig;

    }

    public byte[] sign(InputStream is) {
      return sig;

    }

    public void modifySigningDictionary(PdfDictionary signDic) {
    }

}

Getting error on MakeSignature.signDeferred() as follows:

Exception in thread "main" com.itextpdf.text.DocumentException: No field at com.itextpdf.text.pdf.security.MakeSignature.signDeferred(MakeSignature.java:291) at test.SignerFinal.main(SignerFinal.java:219)

search answers on this forum

1

There are 1 answers

2
mkl On

The issue already is visible in your abstract steps:

step 1 - preparing the pdf
step 2 - calculating the hash
step 3 - signing the hash
step 4 - combine hash to the source pdf

In the last step you say that you plan to combine the (signed) hash with the source PDF. This of course is wrong, you have to combine it with the prepared PDF from step 1!

In your code, therefore, you have to replace

//step 4 - combine hash to the source pdf                                   
reader = new PdfReader(src);
FileOutputStream os1 = new FileOutputStream(dest);
ExternalSignatureContainer external1 = new MyExternalSignatureContainer(SignHashedPDF);
MakeSignature.signDeferred(reader, "sig1", os1, external1);
os.close();

with something like

//step 4 - combine hash to the prepared pdf
os.close();
reader = new PdfReader(dest);
String signed = "signed_dest.pdf";
FileOutputStream os1 = new FileOutputStream(signed);
ExternalSignatureContainer external1 = new MyExternalSignatureContainer(SignHashedPDF);
MakeSignature.signDeferred(reader, "sig1", os1, external1);

Furthermore, your variable names and your comments make me assume that your SignHashedPDF is a mere naked signed hash, not a complete CMS signature container. But MakeSignature.signDeferred for a ADBE_PKCS7_DETACHED signature field value expects a CMS signature container!

If my assumption is correct, you will need to change your step 3 accordingly...