I'm developing a client-server application where clients have to sign PDF documents using their signatures and upload them to the server. The task is complicated by the fact that clients don't have the means to embed signatures into PDFs, they can only read raw bytes and produce the signature in the form of raw bytes.
I'm trying to implement the following workflow:
- The client uploads the unsigned PDF to the server
- The server opens the PDF, extracts the bytes that the client needs to sign, and sends those bytes back
- The client receives these bytes, signs them using a client certificate and sends the signature to the server
- The server embeds the received signature into the PDF it received earlier.
I found some code samples of extracting bytes to sign and embedding the signature bytes into the PDF (this is the main sample I'm using).
The problem is that this sample performs all the steps in one program, it embeds the signature right after getting the document hash without closing PdfStamper
. What I need is some way to save the document after adding the signature field and getting sha.Hash
, and then at some later time (when the server receives the computed signature) open the document and embed the signature value into the PDF.
Can you suggest a way to modify this code so that the steps (2) and (4) can be independent, and not require shared instances of PdfReader
and PdfStamper
?
The answer below was taken from our white paper on digital signatures, chapter 4, section 4.3.3 Signing a document on the server using a signature created on the client. Code examples here
The desired workflow can be seen as 3 major steps:
Presign:
Required: pdf, certificate chain
Serverside, setup signature infrastructure, extract message digest and send the digest to client as a byte-array
Signing:
Required: message digest as byte-array, private key
Clientside, apply cryptographic algorithms to message digest to generate the signed digest from the hash and send this signature to the server
Code examples, iText5 and C#:
Presign (server)
Signing (client)
Postsign (server)
I've omitted most of the client-server communication code and focused on the signing logic. I've also not thoroughly tested these snippets, as I had to convert them from java code and I don't currently have a client-server setup to test them with, so copy and run at your own risk.
Figured it out myself. This piece of code pointed me to the right direction.
Turns out the process on the server has to be the following:
The relevant server code:
Side note: what bothers me in all those iText samples is the presence of magic numbers (like
8192
here) without any comments. This makes using this library so much more difficult and annoying than it could be.