How to Obtain the Digital Signature From a Signed PDF Document?

Question:
How can I extract the digital signature from a PDF that has been already signed?

Answer:

To obtain the certificate, you will need to locate the signature form field and get its value. For example:
PDFDoc doc = ... if (doc.HasSignatures()) { Field sigField = doc.GetField("My SignatureField's Name"); // you will need to know the name of the signature field. Obj value = sigField.GetValue(); // value is the signature dictionary and has the following: // 1. Type // 2. Filter // 3. ByteRange // 4. Contents // The Contents entry in the signature dictionary will contain the signature envelope which will hold the public certificate which can be used to verify the signature. }

Question:

How do I get the date, location, name, etc. of the signature?

Answer:

While the digital signature certificate defined in the Contents entry, mentioned above, may contain this information, the PDF can also.

The following code will iterate all the digital signatures in a PDFDoc object, and print out the string metadata for that signature. The switch statement also includes the other possible entries, though these other ones are non-text. See PDF32000_2008 PDF 1.7, Section 12.8.1 Digital Signatures General, Table 252 “Entries in a signature dictionary” for details of these other entries.

`
if(!doc.hasSignatures()) return;

FieldIterator fitr = doc.getFieldIterator();
while(fitr.hasNext())
{
Field field=(Field)(fitr.next());
int type = field.getType();
if(type != Field.e_signature) continue;
Obj value = field.getValue();
if(value == null || !value.isDict()) continue;

System.out.println("========================================");
System.out.println(field.getName());
for (DictIterator itr = value.getDictIterator(); itr.hasNext(); itr.next())
{
String k = itr.key().getName();
switch(k)
{
// case “Filter”:
// case “SubFilter”:
// case “Contents”:
// case “Cert”:
// case “Reference”:
case “ByteRange”:
for (int i = 0; i < itr.Value().Size(); i += 2 )
{
int offset = (int)itr.value().getAt(i).getNumber();
int length_in_bytes = (int)itr.value().getAt(i + 1).getNumber();
System.out.println(“ByteRange " + offset + “-” + (offset + length_in_bytes - 1));
}
break;
case “Changes”:
Obj v = itr.value();
if(v.isArray() && v.size() == 3)
{
int num_pages_altered = (int)v.getAt(0).getNumber();
int num_fields_altered = (int)v.getAt(1).getNumber();
int num_fields_filled = (int)v.getAt(2).getNumber();
System.out.println(num_pages_altered + " Pages Altered\n” + num_fields_altered + " Fields Altered\n" + num_fields_filled + " Fields Filled in");
}
break;
case “Name”:
case “M”:
case “Location”:
case “Reason”:
case “ContectInfo”:
System.out.println(k + " : " + itr.value().getAsPDFText());
break;
case “R”:
case “V”:
System.out.println(k + " : " + itr.value().getNumber());
break;
// case “Prop_Build”:
// case “Prop_AuthTime”:
// case “Prop_AuthType”:
}
}
System.out.println("========================================");
}
`