For a signed PDF document, with invisible signature, I am using PDFBox library to extract signer information, but it's coming as null. Same code works fine for visible signature. Can someone help on this if we need to make?
//Load PDF Document
PDDocument document = PDDocument.load(doc);
//Iterate each Signature
for (PDSignature pdSignature : document.getSignatureDictionaries()) {
if (pdSignature != null) {
HashMap values = new HashMap();
String subFilter = pdSignature.getSubFilter();
if (subFilter != null) {
LOG.debug("---------Siganature Details---------- ");
LOG.debug("Signer Name : " + pdSignature.getName());
values.put(SignerName, pdSignature.getName());
pdSignature.getName()
returns the value of the Name entry of the signature dictionary. But this entry is optional:
Name text string (Optional) The name of the person or authority signing the document. This value should be used only when it is not possible to extract the name from the signature.
Generally you'll have to analyze the signer certificate in the embedded signature container to get the common name of the signer.
As @Tilman pointed out in a comment, the pdfbox example ShowSignature shows quite a number of means to retrieve data from a CMS signature container.
In a comment you write
Only the complete principal string can be extracted which contains the complete string using the below code "certFromSignedData.getSubjectX500Principal().toString()" [...] Any direct way of querying CN name alone?
Indeed you only get the complete subject distinguished name if you apply toString()
to the X500Principal
returned by certFromSignedData.getSubjectX500Principal()
. But if you create a sun.security.x509.X500Name
for it, you can easily retrieve the common name:
X500Principal principal = certFromSignedData.getSubjectX500Principal();
sun.security.x509.X500Name name = sun.security.x509.X500Name.asX500Name(principal);
System.out.printf("Whole DN: %s\n", name);
System.out.printf("CN: %s\n", name.getCommonName());
If you don't want to use sun.security.x509
classes, you can similarly use BouncyCastle classes, starting from the matching BouncyCastle X509CertificateHolder
:
org.bouncycastle.asn1.x500.X500Name name = certificateHolder.getSubject();
System.out.printf("Whole DN: %s\n", name);
RDN[] cns = name.getRDNs(BCStyle.CN);
System.out.printf("CN: %s\n", cns.length > 0 ? cns[0].getFirst().getValue() : null);
however it's in different format for invisible and visible signature. For visible signature: SERIALNUMBER=xxxx, DNQ=xxx, EMAILADDRESS=xx, SURNAME=xx, GIVENNAME=xx, C=xx, CN=xx and for invisible signature "CN="xx" + EMAILADDRESS=xx, OU=xx, O="xx", L=xx, ST=xx, C=xx".
Which attributes are used in the subject DN and whether RDNs with multiple attribute/value pairs are used, depends on the signer certificate alone, it does not have anything to do with visible and invisible signature. If you have distinct specific patterns for invisible and visible signatures, then your test PDF pool is biased.