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 ! =)
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);