PAdES and PDF Java Toolkit Part 3 : PAdES BES/EPES

PAdES and PDF Java Toolkit Part 3 : PAdES BES/EPES

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
  • content-time-stamp

For PAdES EPES there are two additional attributes that may be specified :

  • signature-policy-identifier
  • commitment-type-indication

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
  • counter-signature
  • 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.

AddPAdESEPES Sample

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.

[sourcecode language=”java”]
// Use CAdES signature options
SignatureOptionsCADES sigOptions = SignatureOptionsCADES.newInstance();
[/sourcecode]

Next, we create a subfilter for our signature to use, specifying that the filter should be ETSI.CADES.detached.

[sourcecode language=”java” firstline=”4″]
// Create the required subfilter object for PAdES BES/EPES
PDFSignatureSubFilter filter = PDFSignatureSubFilter.getInstance(PDFSignature.k_ETSI_CADES_detached);

sigOptions.setSubFilter(filter);
[/sourcecode]

Then allow the policy information to be stored

[sourcecode language=”java” firstline=”8″]
// Enable storing policy information as a signed attribute in the certificate
sigOptions.setEnablePolicyInformationInSigningCertificateAttribute(true);
[/sourcecode]

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.

[sourcecode language=”java” firstline=”10″]
// Comment the following line to make this sample produce a PAdES-BES compliant document
sigOptions.setEnableSignaturePolicyIdentifierAttribute(true);
[/sourcecode]

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.

[sourcecode language=”java” firstline=”12″]
// Set the user info
UserInfo userInfo = UserInfo.newInstance("Datalogics", "Chicago, Illinois", "Example usage of PDFJT", "Datalogics");
sigOptions.setUserInfo(userInfo);
[/sourcecode]

Then continue as normal and create the signature field.

[sourcecode language=”java” firstline=”15″]
// Create an unsigned signature field.
SignatureFieldInterface sigField = SignatureFieldFactory.createSignatureField(page, annotRect, iform);
[/sourcecode]

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.

[sourcecode language=”java” firstline=”17″]
// Must use a SignatureServiceProvider that implements a CADESDetachedSigner
// PDFJT supplies the CertJNonFIPSProvider that implements this functionality
CryptoContext cryptoContext = new CryptoContext(CryptoMode.NON_FIPS_MODE, "SHA1", "RSA");
SignatureServiceProvider defaultCryptoProvider = new CertJNonFIPSProvider(cryptoContext);
[/sourcecode]

Create a SignatureManager object.

[sourcecode language=”java” firstline=”21″]
SignatureManager sigMgr = SignatureManager.newInstance(pdfDoc);
[/sourcecode]

Finally specify that the document should be signed with a CADES Detached profile by using signWithCADESDetached and pass in the objects that we created.

[sourcecode language=”java” firstline=”22″]
// Sign and save the document.
sigMgr.signWithCADESDetached(sigField, sigOptions, credentials, byteWriter, defaultCryptoProvider);
[/sourcecode]

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.

One thought on “PAdES and PDF Java Toolkit Part 3 : PAdES BES/EPES

Leave a Reply

Your email address will not be published. Required fields are marked *