Search code examples
javapdfboxdigital-signature

PDFBox : Signature fails "Can't write signature, not enough space"


I implemented a signature feature in JAVA using PDFBox.

The signing part of my code is :

            ExternalSigningSupport externalSigning = document.saveIncrementalForExternalSigning(output);
            byte[] cmsSignature = new byte[0];
            
            try {
                
                Certificate[] certificationChain = SignatureUtils.getCertificateChain(alias);
                X509Certificate certificate = (X509Certificate) certificationChain[0];
                PrivateKey privateKey = SignatureUtils.getSignaturePrivateKey(alias, password);
                
                CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
                ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA256WithRSA").build(privateKey);
                gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().build())
                                .build(sha1Signer, certificate));
                gen.addCertificates(new JcaCertStore(Arrays.asList(certificationChain)));
                CMSProcessableInputStream msg = new CMSProcessableInputStream(externalSigning.getContent());
                CMSSignedData signedData = gen.generate(msg, false);
                
                if (tsaUrl != null && !tsaUrl.isEmpty()) {
                    ValidationTimeStamp validation;
                    validation = new ValidationTimeStamp(tsaUrl);
                    signedData = validation.addSignedTimeStamp(signedData);
                }
                cmsSignature = signedData.getEncoded();
                
                if (logger.isDebugEnabled()) {
                    logger.debug("signature length = " + cmsSignature.length);
                    logger.debug("certificate = " + certificate.toString());
                }
                
            } catch (GeneralSecurityException | CMSException | OperatorCreationException | IOException e) {
                throw new SignatureException(e.getMessage());
            }
            
            externalSigning.setSignature(cmsSignature);

Everything works fine if I use my testing auto-signed certificate I generated with the keytool command.

The problem is, when I try this code with an existing certificate which is truly certified, I get the exeption :

Caused by: java.io.IOException: Can't write signature, not enough space
        at org.apache.pdfbox.pdfwriter.COSWriter.writeExternalSignature(COSWriter.java:797)
        at org.apache.pdfbox.pdmodel.interactive.digitalsignature.SigningSupport.setSignature(SigningSupport.java:48)

I have no idea why this doesn't work...

Any help would be appreciated ! =)


Solution

  • In a comment you mention that you get

    signature length = 10721

    in the log files and that you

    didn't set any preferred size

    By default PDFBox reserves 0x2500 bytes for the signature. That's 9472 bytes decimally. Thus, just like the exception says, there's not enough space.

    You can set the size PDFBox reserves for the signature by using a SignatureOptions object during document.addSignature:

    SignatureOptions signatureOptions = new SignatureOptions();
    signatureOptions.setPreferredSignatureSize(20000);
    document.addSignature(signature, signatureOptions);