add digital signatures to pdf using mssp

The code in the question is based on a multi-phase approach:

  • Sign the PDF injecting an empty byte array as signature container (by use of the ExternalBlankSignatureContainer).
  • Calculate the digest to sign (here incorrectly a digest for the whole file from the previous step is calculated, the digest must be calculated for the whole file except the signature container placeholder).
  • Request signature container for that document hash.
  • Inject signature container into the placeholder in the file from the first step.

If the signature server can take a long time to return a signature container, such an approach is appropriate but in the case at hand comments clarify

The server gives response quickly(just few seconds)

In such a use case one should proceed in a single step approach (as far as iText signing API calls are concerned):

PdfReader reader = new PdfReader(...);
PdfStamper stamper = PdfStamper.createSignature(reader, ..., '\0');
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "Signature");
ExternalSignatureContainer external = new RemoteSignatureContainer();
MakeSignature.signExternalContainer(appearance, external, 8192);

with a custom ExternalSignatureContainer implementation RemoteSignatureContainer:

class RemoteSignatureContainer implements ExternalSignatureContainer {

    public byte[] sign(InputStream data) throws GeneralSecurityException {
        [return a CMS signature container signing the data from the InputStream argument]

    public void modifySigningDictionary(PdfDictionary signDic) {
        signDic.put(PdfName.FILTER, PdfName.ADOBE_PPKLITE);
        signDic.put(PdfName.SUBFILTER, PdfName.ADBE_PKCS7_DETACHED);

I don’t know your API to access your signature server but based on your UPDATE 2 I assume the sign method in your RemoteSignatureContainer would look like this:

public byte[] sign(InputStream data) throws GeneralSecurityException {
    MessageDigest messageDigest = MessageDigest.getInstance("SHA256");
    byte[] messageHash  = messageDigest.digest(StreamUtil.inputStreamToArray(data));
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < messageHash.length; ++i) {
        sb.append(Integer.toHexString((messageHash[i] & 0xFF) | 0x100).substring(1, 3));

    String msisdn = "97688888888";
    try {
        Client client = new Client(msisdn, sb.toString());

        String strResult = client.sendRequest();
        JSONObject jsonResult = new JSONObject(strResult);
        String base64Signature = jsonResult

        return Base64.getDecoder().decode(base64Signature);
    } catch (IOException | JSONException e) {
        throw new GeneralSecurityException(e);

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top