So, you’ve made it through the first two parts of this series and are back for more? You must really be interested in working with PAdES and our PDF Java Toolkit. Just in case you are new to this series and missed the first two parts here are links to them so you can catch up before continuing :
This time around we will be discussing two of the more advanced PAdES profiles, PAdES Basic Electronic Signatures (BES) and PAdES Explicit Policy Electronic Signatures (EPES). These profiles are very similar to each other and parallel the requirements in the CAdES BES and CAdES EPES profiles. Since PAdES BES and PAdES EPES are so similar we will focus our discussion on the BES version of PAdES and point out where the EPES version has extra requirements. Before we dive into the code that makes up our sample for these PAdES profiles, let’s discuss the extra requirements for these profiles.
Requirements of PAdES BES/EPES
The PAdES specification divides the outline of these profiles into two sections, required attributes and optional (but highly suggested!) attributes. Both the required and optional attributes are only meant to further the verification of the signer so that you can fully trust that the document came from the signatory you expected and that the document has not been tampered with by a third party by way of a certificate substitution attack.
The basis for these profiles is the PAdES Basic profile, this means that just like for PAdES Basic, PAdES BES/EPES signatures also have the following restriction
- ByteRange must cover the entire document, including the signature dictionary but excluding the PDF Signature itself
In addition to this PAdES BES and PAdES EPES require the following :
- subfilter must be ETSI.CAdES.detached
- signature dictionary can not contain a cert entry
- a single SignerInfo entry shall be present in a signature
- content-type must be set to id-data
- message-digest must use syntax as defined by RFC 3852 Cryptographic Message Syntax (CMS)
- signing-certificate or signing-certificate-v2 must be used as a signed attribute
These are the required attributes that PDF Signatures must incorporate in order to comply with PAdES BES or PAdES EPES. There are a few optional attributes that can be set for both of these profiles (for a complete list please read Part 3 of the PAdES specification) :
- signature time stamp
- signer attributes
For PAdES EPES there are two additional attributes that may be specified :
Even though this section is outlined as optional attributes some of the attributes that are discussed are actually not allowed. The following attributes are not allowed for PAdES BES or PAdES EPES :
- signing time
- content reference
- content identifier
- content hints
- signer location
That seems like it would require a decent amount of effort to ensure that your signatures comply with the PAdES specification. Lucky for us though, PDFJT takes care of that for us as long as we provide it a few extra pieces of data before signing our documents.
This time around we will skip over creating the credentials object (it is the same as with the PAdES Basic sample that we discussed last time) and we will jump right into the heart of the sample.
We start again by creating a SignatureOptionsCADES object.
// Use CAdES signature options SignatureOptionsCADES sigOptions = SignatureOptionsCADES.newInstance();
Next, we create a subfilter for our signature to use, specifying that the filter should be ETSI.CADES.detached.
// Create the required subfilter object for PAdES BES/EPES PDFSignatureSubFilter filter = PDFSignatureSubFilter.getInstance(PDFSignature.k_ETSI_CADES_detached); sigOptions.setSubFilter(filter);
Then allow the policy information to be stored
// Enable storing policy information as a signed attribute in the certificate sigOptions.setEnablePolicyInformationInSigningCertificateAttribute(true);
If you are only interested in creating a PAdES BES compliant signature you can skip the next line. This line tells PDFJT to add the signature policy identifier to the signature.
// Comment the following line to make this sample produce a PAdES-BES compliant document sigOptions.setEnableSignaturePolicyIdentifierAttribute(true);
To set the signer info PDFJT supplies a UserInfo object. This is where you set attributes like company name, location, and reason for the signature.
// Set the user info UserInfo userInfo = UserInfo.newInstance(&amp;quot;Datalogics&amp;quot;, &amp;quot;Chicago, Illinois&amp;quot;, &amp;quot;Example usage of PDFJT&amp;quot;, &amp;quot;Datalogics&amp;quot;); sigOptions.setUserInfo(userInfo);
Then continue as normal and create the signature field.
// Create an unsigned signature field. SignatureFieldInterface sigField = SignatureFieldFactory.createSignatureField(page, annotRect, iform);
In most cases the standard SignatureServiceProvider would be acceptable but for PAdES BES or EPES we need to go above and beyond by telling PDFJT to use a SignatureServiceProvider that has access to the CryptoJ library in Java. This is done by creating a new CryptoContext and using that object to create a CertJNonFIPSProvider.
// Must use a SignatureServiceProvider that implements a CADESDetachedSigner // PDFJT supplies the CertJNonFIPSProvider that implements this functionality CryptoContext cryptoContext = new CryptoContext(CryptoMode.NON_FIPS_MODE, &amp;quot;SHA1&amp;quot;, &amp;quot;RSA&amp;quot;); SignatureServiceProvider defaultCryptoProvider = new CertJNonFIPSProvider(cryptoContext);
Create a SignatureManager object.
SignatureManager sigMgr = SignatureManager.newInstance(pdfDoc);
Finally specify that the document should be signed with a CADES Detached profile by using signWithCADESDetached and pass in the objects that we created.
// Sign and save the document. sigMgr.signWithCADESDetached(sigField, sigOptions, credentials, byteWriter, defaultCryptoProvider);
This is a bit code than the PAdES Basic sample but it is still relatively small and easy to understand I hope. Next week there will be even more code as we dive into PAdES Long Term Validation, a profile that is designed to be used in conjunction with PAdES Basic, PAdES BES, or PAdES EPES to incorporate a time stamp signature. Make sure to come back next week for the exciting conclusion of our mini blog series on PAdES and PDFJT.