• No results found

Retrieving information from a signature

In document Digital Signatures 20130304 (Page 126-131)

5. Validation of signed documents

5.2 Retrieving information from a signature

Using the verifySignature() method from code sample 5.2, we checked the integrity of signed documents, but we didn’t retrieve much information about the signatures.

5.2.1 Overview of the information stored in a signature field and dictionary

Code sample 5.3 uses this method, but also returns useful info about the signature field, the signature field’s widget annotation, the signature dictionary, the signature, and the signer.

Code sample 5.3: Retrieving information from a signature

public SignaturePermissions inspectSignature(

AcroFields fields, String name, SignaturePermissions perms) throws GeneralSecurityException, IOException {

List<FieldPosition> fps = fields.getFieldPositions(name);

Digital Signatures for PDF documents 2012

PdfPKCS7 pkcs7 = super.verifySignature(fields, name);

System.out.println("Digest algorithm: " + pkcs7.getHashAlgorithm());

System.out.println("Encryption algorithm: " + pkcs7.getEncryptionAlgorithm());

System.out.println("Filter subtype: " + pkcs7.getFilterSubtype());

X509Certificate cert = (X509Certificate) pkcs7.getSigningCertificate();

System.out.println("Name of the signer: " +

CertificateInfo.getSubjectFields(cert).getField("CN"));

if (pkcs7.getSignName() != null)

System.out.println("Alternative name of the signer: "

+ pkcs7.getSignName());

SimpleDateFormat date_format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SS");

System.out.println("Signed on: " +

date_format.format(pkcs7.getSignDate().getTime()));

if (pkcs7.getTimeStampDate() != null) { System.out.println("TimeStamp: " +

date_format.format(pkcs7.getTimeStampDate().getTime()));

TimeStampToken ts = pkcs7.getTimeStampToken();

System.out.println("TimeStamp service: " + ts.getTimeStampInfo().getTsa());

System.out.println("TimeStamp verified? "+ pkcs7.verifyTimestampImprint());

}

System.out.println("Location: " + pkcs7.getLocation());

System.out.println("Reason: " + pkcs7.getReason());

PdfDictionary sigDict = fields.getSignatureDictionary(name);

PdfString contact = sigDict.getAsString(PdfName.CONTACTINFO);

if (contact != null)

System.out.println("Contact info: " + contact);

perms = new SignaturePermissions(sigDict, perms);

System.out.println("Signature type: " +

(perms.isCertification() ? "certification" : "approval"));

System.out.println("Filling out fields allowed: " + perms.isFillInAllowed());

System.out.println("Adding annotations allowed: " + perms.isAnnotationsAllowed());

for (FieldLock lock : perms.getFieldLocks()) { System.out.println("Lock: " + lock.toString()); contains the widget annotation and the coordinates on that page representing the field —assuming there is such a page. As defined in the PDF specification, an invisible signature field will have a widget annotation with a zero width or height. A signature field will also be invisible if the Hidden of NoView flag of the widget annotation are set.

Digital Signatures for PDF documents 2012

Next, we use the PdfPKCS7 object and two of its methods —getHashAlgorithm() and getEncryptionAlgorithm()— to find out how the message digest of the PDF bytes was created and how these bytes and additional attributes were signed. The getFilterSubtype() will tell you how the signed bytes are stored in the PDF (see section 2.1.1).

We need the signing certificate if we want to know the name of the signer. We cast the result of the getSigningCertificate() method to an X509Certificate object, and we can use the CertificateInfo helper class to get more info, for instance: the subject fields. In this example, we only retrieve the Common Name (“CN”). If you look at code sample 1.9 showing the contents of a public certificate, you see that we could also ask for information such as the Organization (“O”), the Organizational Unit (“OU”), and so on. We’ll do much more with certificates in the next section.

NOTE: The getSignName() usually doesn’t return any information. That specific field in the signature dictionary should only be used when somebody wants to sign a document and his name can’t be retrieved from the certificate.

We can get the time on the clock of the computer of the signer using the getSignDate() method.

If a timestamp was applied, we need the getTimeStampDate() method. You can check if the timestamp covers the document with the verifyTimestampImprint() method. As we’re using BouncyCastle to verify signatures, we can also retrieve a TimeStampToken object. This object gives you access to the TimeStampInfo which reveals plenty of information on the TSA. This is the object you need if you want to check the TSA’s certificate.

The PdfPKCS7 object has methods for the most common entries in the signature dictionary, such as getLocation() and getReason(). If you want less common entries, such as the contact info, you should use the getSignatureDictionary() method and get the properties by name.

We also need the signature dictionary if we want to create a SignaturePermissions object.

Every new signature can add more restrictions to a document, but it can’t take away previous restrictions. That explains why you need to pass the SignaturePermissions instance of the previous signature, or null if there was none. We can use this class to check whether the signature was meant for certification, or for approval. We can also check the MDP settings: is form filling and adding extra signatures allowed? Is adding annotations allowed? Finally, we can also list the locks that are set on the fields.

5.2.2 Inspecting signatures

If we return to the PDF from figure 2.31, and inspect the signatures, we get the following output:

results/chapter2/step_4_signed_by_alice_bob_carol_and_dave.pdf

===== sig1 =====

Field on page 1; llx: 36.0, lly: 740.0, urx: 559.0; ury: 790.0 Signature covers whole document: false

Document revision: 1 of 4 Integrity check OK? true Digest algorithm: SHA256 Encryption algorithm: RSA

Filter subtype: /adbe.pkcs7.detached Name of the signer: Alice Specimen Signed on: 2012-09-17 18:03:44.00

Digital Signatures for PDF documents 2012

Field on page 1; llx: 36.0, lly: 654.0, urx: 559.0; ury: 704.0 Signature covers whole document: false Name of the signer: Bob Specimen Signed on: 2012-09-17 18:03:44.00

Field on page 1; llx: 36.0, lly: 568.0, urx: 559.0; ury: 618.0 Signature covers whole document: false Name of the signer: Carol Specimen Signed on: 2012-09-17 18:03:44.00

Field on page 1; llx: 36.0, lly: 482.0, urx: 559.0; ury: 532.0 Signature covers whole document: true Name of the signer: Dave Specimen Signed on: 2012-09-17 18:03:44.00

Digital Signatures for PDF documents 2012

Lock: /Exclude[approved_dave, sig4]

Lock: /All

All revisions were signed using SHA256 with RSA, and the /adbe.pkcs7.detached sub filter. We didn’t add any location, reason, or contact info, but we gradually added restrictions. The first signature was a certification signature that didn’t allow adding annotations. The subsequent signatures were approval signatures for which a field lock dictionary was defined. Approval signatures allow adding annotations, but as this was already restricted for the first revision, the restriction remains valid for the revisions that follow. The document is completely locked with the fourth revision.

In the next example, we’re inspecting a document that was timestamped:

results/chapter3/hello_token.pdf

===== sig =====

Field on page 1; llx: 36.0, lly: 748.0, urx: 144.0; ury: 780.0 Signature covers whole document: true Name of the signer: Bruno Lowagie Signed on: 2012-09-17 17:34:43.00 TimeStamp: 2012-09-17 17:34:54.392 TimeStamp service: 4:

OU=SEIKO Precision Inc.,[email protected],O=GlobalSign, CN=SEIKO Timestamp Service. Advanced AW02-001

Timestamp verified? true accuracy of the timestamp from the TimeStampInfo object. There’s a lot more to explore than what is revealed in this simple example.

Finally, this is the output of the example we made using code sample 2.12:

results/chapter2/field_metadata.pdf

===== Signature1 =====

Field on page 1; llx: 41.3671, lly: 713.71, urx: 237.353; ury: 781.258 Signature covers whole document: true Name of the signer: Bruno Specimen

Alternative name of the signer: Bruno L. Specimen Signed on: 2012-08-05 00:00:00.00

Location: Ghent Reason: Test metadata

Digital Signatures for PDF documents 2012

Contact info: 555 123 456 Signature type: approval

Filling out fields allowed: true Adding annotations allowed: true

In section 2.4.3, we added metadata such as a phone number and an alternative name for Bruno Specimen. With code sample 5.3, we are able to retrieve that data.

Now that we have more information about the signature, we already have an idea about who signed the document, but we need to verify the certificates with the CA who issued them to find out if the certificate were valid at the moment of signing. That’s what the next section is about.

In document Digital Signatures 20130304 (Page 126-131)