Welcome back to our discussion about working with the PDF Java Toolkit and PAdES (PDF Advanced Electronic Signatures). In case you missed the first part of this series please feel free to stop here and read it, I’ll wait here for you.
Okay, so you read the first part of this series right? Good! This week before we continue our discussion I’d like to take a step back and talk about digital signatures as they exist in ISO 32000.
Digital Signatures in ISO 32000
Digital signatures as defined in ISO 32000 are “used to authenticate the identity of a user and the document’s contents”. The information that is required to digitally sign a PDF is stored in the PDF’s signature dictionary as part of the signing process. This signature dictionary can have many different entries, for this discussion we will focus on the ByteRange entry, which contains the range of bytes that the digital signature protects in the document. ISO 32000 specifies that the byte range for a digital signature can cover any range within a document but that it is typical for the range to cover the entire document, excluding the signature itself. This is where the PAdES specification diverges from ISO 32000.
The PAdES Basic Profile
The PAdES Basic profile takes the requirements for digital signatures above and beyond what ISO 32000 states by requiring that the byte range protect the entire document, still excluding the signature itself. This requirement ensures that the contents of the entire document are protected by the signature so that users who receive your signed document know that the document has not been tampered with. This is not where the PAdES Basic profile stops though, it goes one step further and requires that digital signatures conform to PKCS #7. ISO 32000 allows either PKCS #7 or PKCS #1 to be used when digitally signing a document. These requirements that are laid out as part of the PAdES Basic profile do not fall outside of ISO 32000 though, they are all options that ISO 32000 provides, so there are a good number of digital signatures that already conform to this profile.
AddPAdESBasic Sample in PDFJT
In our September 6, 2012 release of PDFJT we added a sample named AddPAdESBasic. This sample takes a document and adds a digital signature, using the PDFJT evaluation credentials, that complies with the PAdES Basic profile.
The first piece of this sample that we want to take a look at is how it creates a Credentials object. A Credentials object is what stores the certificate and private key that should be used for signing a document. In this sample we have a helper method. createCredentials that takes care of reading in the certificate and private key for us.
// Read in the PDFJT evaluation certificate and key // to create a Credentials object from Credentials credentials = createCredentials();
The next step is to create a SignatureFieldInterface, this is the object that represents a signature field in a PDF. In order to create a signature field we need to supply PDFJT with a PDFPage (the page object mentioned in the source below), a PDFRectangle (annotRect), and a PDFInteractiveForm (iform).
// Create an unsigned signature field. // // page - PDFPage object that we want to put the signatures appearance on // annotRect - the rectangular space that the signatures appearance should take up // iform - the parent object of the signature, in this case an interactive form SignatureFieldInterface sigField = SignatureFieldFactory.createSignatureField(page, annotRect, iform);
Next, we create a SignatureOptionsCADES object so that we can set the subfilter to one of the two subfilters that the PAdES Basic profile allows.
// Use CADES signature options SignatureOptionsCADES options = SignatureOptionsCADES.newInstance(); // Set the subfilter to PKCS7 SHA1 options.setSubFilter(PDFSignatureSubFilter.PKCS7Sha1);
If you do not want to use the SHA-1 filter, PAdES Basic profile also allows the use of the PKCS7Detached subfilter.
Now all that is left to do is create a SignatureManager that we will use to sign our document.
// Create a signature manager that will perform the signing operation SignatureManager sigMgr = SignatureManager.newInstance(pdfDoc); // Sign and save the document sigMgr.sign(sigField, options, credentials, byteWriter);
That’s all there is to it! Signing the document will write out a signed copy, to the file name that was specified when creating the byte writer, and leave the original file intact.
The above code though only gets the signature to the minimum requirements for the PAdES Basic profile. There are other features (time stamping the signature, including revocation information, the reason for the signature) that this profile recommends that users add but they are not required for this profile but are required for the more advanced profiles that we will start discussing next week.