I'm trying to build an application where the following happens:
- A client requests a PDF-hash from the server.
- The server generates the hash of a PDF-file and sends this to the client.
- The client signs this hash with his private key and sends the signed hash along with the public part of his own certificate.
- The server generates a new, signed PDF file.
The problem I'm having with this: It seems impossible for the server to generate a to-be-signed hash without having the client's certificate available beforehand. I'd really prefer to create a solution where the server does not need to know the client's certificate in order to create the document digest.
All the examples I have found so far use the PdfPKCS7.getAuthenticatedAttributeBytes function to get the to-be-signed hash, but this requires a client certificate to be known. I have looked at the "Digital Signatures for PDF documents" white paper by Bruno Lowagie, but I failed to see exactly what information is digested.
Here's a code snippet of my current attempt:
public byte[] simplePresign(String src, String digestAlgorithm) throws IOException, DocumentException, GeneralSecurityException {
this.digestAlgorithm = digestAlgorithm;
tsaClient = new CustomTSAClient();
PdfReader reader = new PdfReader(src);
os = new ByteArrayOutputStream();
PdfAStamper stamper = PdfAStamper.createSignature(reader, os, '\0', PdfAConformanceLevel.PDF_A_1B);
appearance = stamper.getSignatureAppearance();
PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
appearance.setCryptoDictionary(dic);
HashMap<PdfName, Integer> exc = new HashMap<PdfName, Integer>();
exc.put(PdfName.CONTENTS, getEstimatedSize(null, tsaClient) * 2 + 2);
appearance.preClose(exc);
InputStream data = appearance.getRangeStream();
MessageDigest mDigest = DigestAlgorithms.getMessageDigest(digestAlgorithm, null);
return DigestAlgorithms.digest(data, mDigest);
}
Unfortunately this hash does not seem to be correct, signing this hash and generating a signed document based on the signed hash leads to an invalid signature.
I would be most grateful if someone can help me improve this code snippet, or otherwise give me some insight in the data that I need to digest for a signature.