0

I tried to sign a document with itext 5.5.10.I first signed my file with an empty signature and then created a SHA1 hash from the file containing the empty signature. I invoke the web service of my TSA to get the signedData.

First part emptySignature

public void emptySignature(String src, String dest, String fieldname) throws IOException, DocumentException, GeneralSecurityException {
    PdfReader reader = new PdfReader(src);

    FileOutputStream os = new FileOutputStream(dest);
    PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
    PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
    appearance.setVisibleSignature(new Rectangle(0,0,0,0), 1, fieldname);
    ExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ETSI_RFC3161);
    MakeSignature.signExternalContainer(appearance, external, 8192);
}

Second part hash pdf

public byte[] getPdfHash(@NotNull Calendar signDate, int estimatedSize, @NotNull String hashAlgorithm,
        boolean isTimestampOnly) throws Exception {

    pdfReader = new PdfReader(inputFilePath, pdfPassword != null ? pdfPassword.getBytes() : null);
    AcroFields acroFields = pdfReader.getAcroFields();
    boolean hasSignature = acroFields.getSignatureNames().size() > 0;

    byteArrayOutputStream = new ByteArrayOutputStream();
    pdfStamper = PdfStamper.createSignature(pdfReader, byteArrayOutputStream, '\0', null, hasSignature);
    pdfStamper.setXmpMetadata(pdfReader.getMetadata());

    pdfSignatureAppearance = pdfStamper.getSignatureAppearance();
    pdfSignature = new PdfSignature(PdfName.ADOBE_PPKLITE,
            isTimestampOnly ? PdfName.ETSI_RFC3161 : PdfName.ADBE_PKCS7_DETACHED);
    pdfSignature.setReason(signReason);
    pdfSignature.setLocation(signLocation);
    pdfSignature.setContact(signContact);
    pdfSignature.setDate(new PdfDate(signDate));
    pdfSignatureAppearance.setCryptoDictionary(pdfSignature);

    // certify the pdf, if requested
    if (certificationLevel > 0) {
        // check: at most one certification per pdf is allowed
        if (pdfReader.getCertificationLevel() != PdfSignatureAppearance.NOT_CERTIFIED)
            throw new Exception(
                    "Could not apply -certlevel option. At most one certification per pdf is allowed, but source pdf contained already a certification.");
        pdfSignatureAppearance.setCertificationLevel(certificationLevel);
    }

    HashMap<PdfName, Integer> exc = new HashMap<PdfName, Integer>();
    exc.put(PdfName.CONTENTS, new Integer(estimatedSize * 2 + 2));

    pdfSignatureAppearance.preClose(exc);

    MessageDigest messageDigest = MessageDigest.getInstance(hashAlgorithm);
    InputStream rangeStream = pdfSignatureAppearance.getRangeStream();
    int i;
    while ((i = rangeStream.read()) != -1) {
        messageDigest.update((byte) i);
    }

    return messageDigest.digest();
}

third part signature

public  void signExternalContainer( byte[] externalSignature, int estimatedSize) throws GeneralSecurityException, IOException, DocumentException {

    InputStream data = pdfSignatureAppearance.getRangeStream();
    byte[] encodedSig =externalSignature;

    if (estimatedSize < encodedSig.length)
        throw new IOException("Not enough space");

    byte[] paddedSig = new byte[estimatedSize];
    Arrays.fill(paddedSig, (byte) 32);
    System.arraycopy(encodedSig, 0, paddedSig, 0, encodedSig.length);

    PdfDictionary dic2 = new PdfDictionary();
    dic2.put(PdfName.CONTENTS, new PdfString(paddedSig).setHexWriting(false));
    pdfSignatureAppearance.close(dic2);
}

i get this error

Exception in thread "main" java.lang.IllegalArgumentException: The key /Contents is too big. Is 8272, reserved 2
at com.itextpdf.text.pdf.PdfSignatureAppearance.close(PdfSignatureAppearance.java:1476)

I tried to fix the error without success. I would like you to help me find a solution. I have based myself on the basic examples of itext. Thank you in advance for your help.

kava
  • 3
  • 4
  • Would you mind to remove the horizontal scollbars, by reformating your source code? Thanks. – Reporter Jun 30 '17 at 12:42
  • 1
    I stopped reading after *then created a SHA1 hash from the file* because you don't seem to know that SHA1 can no longer be used: [Are PDF Signatures shattered?](http://itextpdf.com/blog/are-pdf-signatures-shattered) I hope you also know that you shouldn't hash the *complete* file. Finally, the error explains *exactly* what is going wrong. You didn't reserve sufficient space for the signature. This is explained in the [tutorial](http://pages.itextpdf.com/ebook-digital-signatures-for-pdf.html). – Bruno Lowagie Jun 30 '17 at 12:42
  • I used the default space 8192. But after the signature I found that 2. Definitely I was wrong about how to add space to book. Here is the method I used for booking. `MakeSignature.signExternalContainer(appearance, external, 8192);` – kava Jun 30 '17 at 13:41
  • I just hash byteRange. i use `appearance.getRangeStream()` – kava Jun 30 '17 at 13:44
  • You show us some methods but hide from us how you orchestrate their usage. At first glance it appears possible that one might be able to use the methods to create a valid signature if orchestrated correctly. – mkl Jun 30 '17 at 20:38

0 Answers0