the Belgian eID and PDF:
Forms and Digital Signatures

These are my notes for my GovCamp presentation in Brussels (September 21, 2006; between OSCon and DrupalCon).

I was asked to talk about the Belgian eID; the eID is the new Belgian identity card in the form of a smartcard. I am not an eID expert, so I decided to change the focus of the presentation to a technology I know rather well: the Portable Document Format (PDF).

In this article you will learn:

The conclusion will be that you really don't need to be an eID expert to achieve all this. If I can do it, so can you ;-)


previous page | page 1 | page 2 | page 3 | page 4 | next page

Adding a Signature Field

In chapter 15 of the book on iText you will find examples to create PDF documents with an AcroForm containing button fields, choice fields and text fields, but as I already mentioned on page 1 of this article, a form can also contain signature fields.

In chapter 16 you'll learn how to add a signature field at an absolute position using a private/public key pair. There's also an example that shows how to add an invisible signature. For this demo, we'll create a PDF document with two empty signature fields, and we'll use two different eIDs to sign these fields afterwards. But before we talk about empty signature fields, let's spend some more time on AcroForms.

Retrieving data from a filled in PDF form

On the previous page we have created a PDF document with a PDF form that was filled using the data retrieved from an eID (EIDFormAutoFilled1.pdf). We are now going to open this file using PdfReader and we'll retrieve the default value of the fields to create a new document EIDFormUnsigned.pdf (see EIDFormWithSignature.java).

PdfReader reader = new PdfReader("EIDFormAutoFilled1.pdf");
AcroFields form = reader.getAcroFields();
String name = form.getField(EIDForm.NAME);
Note that this won't work if we use EIDFormAutoFilled2.pdf. The form structure in this 'flattened' PDF is lost. We can no longer retrieve the form field keys and their values.

Creating an empty signature field

Just below the table with the personal data of Robert Specimen, we'll add two signature fields:

PdfAcroForm acroform = writer.getAcroForm();
acroform.addSignature("Signature1", 54, 440, 234, 566);
acroform.addSignature("Signature2", 360, 440, 540, 566);
The values [54, 440, 234, 566] and [360, 440, 540, 566] represent the coordinates of a rectangle.

Have a look at figure 3.1 to see where the two signature fields were added.


figure 3.1: a PDF document with two empty signature fields

Before we sign this document, it is important to understand the different types of signatures that are supported in PDF.

Types of Signatures

I have extracted two pages from the PDF Reference (fifth edition; Portable Document Format version 1.6). I summarized these pages as follows:

a PDF document may contain the following standard types of signatures:

  1. One or more document (or ordinary) signatures. These signatures are sometimes referred to as 'recipient signatures'. If a signed document is modified and saved by incremental update, the data corresponding to the byte range of the original signature is preserved. If the signature is valid, it is possible to recreate the state of the document as it existed at the time of signing.
  2. At most one MDP (modification detection and prevention) signature. This signature is also referred to as an 'author' or 'certifying' signature.
  3. At most two usage rights signatures. We already talked briefly about these signatures on page 1. These signatures can only be added to a document with official Adobe products. They can be used for instance to allow the end user to save a filled in form locally.

In the examples that follow, we'll use iText to add two recipient signatures to EIDFormUnsigned.pdf, then we'll try to add two 'author' signatures to see what happens.

Signing the document

These examples also use the GoDot library written by Danny De Cock. There is one caveat. When you want to use your eID to add your digital signature to a document, you need to enter a PIN code (that's rather obvious: otherwise rogue software could sign any document as soon as you put your eID into a smartcard reader.). The GoDot software uses hardware specific middleware to achieve this. More specifically: these examples will only work with the Vasco Digipass Desk850.


figure 3.2: Vasco Digipass Desk850

This digipass offers secure PIN entry facilities. If you use another smartcard reader, you will need to find the middleware that works with that specific device.

Adding recipient signatures

Suppose our unsigned form is an official document that needs to be read and approved by two different persons, first by me, then by Robert Specimen himself.

First I'll add my own signature using EIDFormRecipient1.java. This code was inspired by an example sent to the iText mailinglist by Philippe Frankinet. This example was in turn inspired by the article How to sign a PDF using iText by Paulo Soares.

(1) BelpicCard scd = new BelpicCard("");
    Certificate[] certs = new Certificate[1];
    certs[0] = scd.getNonRepudiationCertificate();
			
(2) PdfReader reader = new PdfReader("EIDFormUnsigned.pdf");
    FileOutputStream fout = new FileOutputStream("EIDFormSigned1.pdf");
(3) PdfStamper stamper = PdfStamper.createSignature(reader, fout, '\0');
    PdfSignatureAppearance sap = stamper.getSignatureAppearance();
    sap.setCrypto(null, certs, null, PdfSignatureAppearance.SELF_SIGNED);
(4) sap.setReason("GovCamp example: eID and PDF (first recipient)");
    sap.setLocation("Belgium");
(5) sap.setVisibleSignature("Signature1");
(6) sap.setExternalDigest(new byte[128], new byte[20], "RSA");
    sap.preClose();
    PdfPKCS7 sig = sap.getSigStandard().getSigner();
    byte[] content = streamToByteArray(sap.getRangeStream());
    byte[] hash= MessageDigest.getInstance("SHA-1").digest(content);
(7) byte[] signatureBytes = scd.generateNonRepudiationSignature(hash);
    sig.setExternalDigest(signatureBytes, null, "RSA");
    PdfDictionary dic = new PdfDictionary();
    dic.put(PdfName.CONTENTS, new PdfString(sig.getEncodedPKCS1()).setHexWriting(true));
    sap.close(dic);

This code snippet is a little bit too technical to explain in a presentation that may not exceed half an hour, but we can distinguish different parts:

  1. We get the non-repudiation certificate from the smartcard
  2. We read the PDF document with the empty signature fields
  3. We create a PdfStamper object with the purpose of adding a signature
  4. We define the appearance of the signature field (adding a reason and a location)
  5. We select the signature field with name Signature1
  6. We'll use an external digest
  7. The digest is generated on the smartcard reader

When we execute this code, we will be asked to enter our PIN code on the pinpad of the Vasco Digipass 850. If we enter this PIN correctly, the document shown in figure 3.3, EIDFormSigned1.pdf, will be the result.


figure 3.3: a PDF document with a signature; the validity has not been checked

The validity is unknown because the Belgian state used self-signed certificates. Only certificates that are signed by a Certificate Authority (e.g. VeriSign) will be trusted automatically. If we want this specific signature to be validated, we will have to add the certificate of 'Bruno Lowagie' to the list of trusted identities (See chapter 16). Once we have done this, the signature will show a green check mark as is shown in figure 3.4.


figure 3.4: a PDF document with a valid signature.

Now if somebody wants to secretly change the contents of the PDF document, the signature will be invalidated. As an example, we could add the sentence "This changes the revision of the document that was signed by Bruno" with EIDFormSignatureInvalid.java. The result, EIDFormInvalidSignature.pdf, is shown in figure 3.5.


figure 3.5: a PDF document that was changed after being signed

This doesn't mean we can't change the document at all. If we want a document to be signed by multiple recipients, it would be quite annoying if every new signature invalidated all the previous signatures.

We will solve this problem by doing an incremental update of the document. This is a code snippet of EIDFormRecipient2.java:

PdfStamper stamper = PdfStamper.createSignature(reader, fout, '\0', null, true);

Please compare this line with the line marked (3) in the previous code snippet. This line makes sure we don't change the previous revision of the document (and therefore don't invalidate the signature). The rest of the code in EIDFormRecipient2.java is almost identical to EIDFormRecipient1.java

The result is shown in figure 3.6.


figure 3.6: a PDF document with 2 signatures (in different revisions)

You could add Robert Specimen's certificate to the list of trusted identities to validate the signature. If we have a close look to the first signature in EIDFormSigned2.pdf, we see that it is marked with a small yellow triangle containing an exclamation point. That's because the document as we see it now is a second revision. The first signature only covers the first revision.

In chapter 16 of iText in Action, you can learn how to verify signatures programmatically, and how to extract the original revision that was signed by the first recipient.

Adding an author signature

Adding an author signature is almost as simple as adding a recipient signature. It's sufficient to add one line (please compare EIDFormAuthor1.java with EIDFormRecipient1.java).

sap.setCertified(true);

When we open the EIDFormCertified1.pdf a special dialog box will open saying the document was certified by Bruno Lowagie (assuming that you have added my certificate in your list of trusted identities).


figure 3.7: a dialog box saying the document was certified by Bruno Lowagie

Figure 3.8 shows how the signature field is visualized.


figure 3.8: a document with a modification detection and prevention signature

Now when we try to change this certified document, for instance by adding a second author signature with EIDFormCertified2.java, the dialog box will warn us that the certification is invalid.


figure 3.9: a warning that the document certification is invalid

We have tried to add two author signatures to one document, but this is not valid according to the PDF Reference, so we end up with a PDF document with an invalid signature: EIDFormInvalid.pdf (see figure 3.10).


figure 3.10: a document can contain only one MDP signature

This example concludes my presentation on PDF Forms and the eID.

previous page | page 1 | page 2 | page 3 | page 4 | next page
top
Author: Bruno Lowagie, August 2006
iText @ Ghent UniversityiText @ Ghent University

Contact | Home | Site Map | Print
© 2006 Bruno Lowagie @ Ghent University, disclaimer