I have client-server architecture where server handles all the PDF related stuff and the client is doing actual signing. Server doesn't have access to a private key, only certificate.
I am having a hard time writing this with PDFbox. I already have a working solution in iText but I am trying to write similar thing with PDFbox. Here is the iText code so you have an insight into what am I trying to achieve.
//before signing on client
StampingProperties stampingProperties = new StampingProperties();
stampingProperties.preserveEncryption();
stampingProperties.useAppendMode();
PdfSigner signer = new PdfSigner(reader, os, stampingProperties);
signer.getDocument().getCatalog().setModified();
X509Certificate[] cert = CertificateHelper.createCertificate(signatureInfo.getCert());
PreSignContainer external = new PreSignContainer(PdfName.Adobe_PPKLite, PdfName.Adbe_pkcs7_detached);
signer.signExternalContainer(external, 8192);
byte[] hash = external.getHash();
PdfPKCS7 sgn = new PdfPKCS7(null, cert, "SHA256", null, new BouncyCastleDigest(), true);
byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, PdfSigner.CryptoStandard.CMS, null, null);
//send sh to client for signing
//after signing on client
try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
PdfPKCS7 sgn = new PdfPKCS7(null, cert, "SHA256", null, new BouncyCastleDigest(), true);
sgn.setExternalDigest(signature, null, "RSA");
byte[] signaturePkcs7 = sgn.getEncodedPKCS7(hash, PdfSigner.CryptoStandard.CMS, getTsaClient(), null, null);
PostSignContainer externalSignatureContainer = new PostSignContainer(signaturePkcs7);
PdfDocument pdfDocument = new PdfDocument(new PdfReader(new ByteArrayInputStream(preSignaturePdf)));
PdfSigner.signDeferred(pdfDocument, storedSignatureInfo.getFieldName(), os, externalSignatureContainer);
byte[] signedPdf = os.toByteArray();
}
This is what I have with PDFbox:
//before signing on client
PDSignature signature = new PDSignature();
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
signature.setLocation(signatureInfo.getLocation());
signature.setReason(signatureInfo.getReason());
signature.setSignDate(Calendar.getInstance());
PDDocument document = PDDocument.load(pdf);
document.addSignature(signature);
ExternalSigningSupport externalSigning = document.saveIncrementalForExternalSigning(os);
byte[] content = externalSigning.getContent().readAllBytes();
byte[] hash = MessageDigest.getInstance("SHA-256", new BouncyCastleProvider()).digest(content);
externalSigning.setSignature(new byte[0]);
//after signing on client
PDDocument pdf = PDDocument.load(preSignaturePdf);
PDSignature lastSignature = pdf.getLastSignatureDictionary();
int offset = lastSignature.getByteRange()[1] + 1;
try (RandomAccessBuffer raf = new RandomAccessBuffer(preSignaturePdf)) {
raf.seek(offset);
raf.write(Hex.getBytes(signature));
}