Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Verify if a PDF is digitally signed with iText

As the title says I want to know if a given PDF file is already digitally signed.

I used iText to sign it but I'm not able to know if it is already signed to eventually resign it or perform other actions.

Is there a way to do it simply (possibly using iText)?

like image 461
Igr Avatar asked Jul 03 '13 11:07

Igr


People also ask

How do you tell if a PDF is electronically signed?

When you open the document with a PDF reader or browser you will see that the document has been given a front page that says that the document is signed. There you will find information about when the document is signed, by whom and what electronic ID that has been used.

How can I verify a PDF digital signature online?

Open the Preferences dialog box. Under Categories, select Signatures. For Verification, click More. To automatically validate all signatures in a PDF when you open the document, select Verify Signatures When The Document Is Opened.

How can you tell if something is electronically signed?

Look for: detailed audit trails documenting each stage of the signing process; software that complies with international eSigning regulations; signer authentication to prove the signer is who they say they are; and.

How can I tell if a PDF is invalid signature?

Open the PDF document in Adobe Reader showing the “At least one signature has problems” error. Click on the Signature Panel button, which will be on the right of the error. Click on the Validate all link. It will prompt the message to validate all signatures depending on the settings.


Video Answer


2 Answers

Using iText:

PdfReader reader = new PdfReader(...);
AcroFields acroFields = reader.getAcroFields();
List<String> signatureNames = acroFields.getSignatureNames();

Now signatureNames contains the names of all reachable signature fields containing signatures, cf. the JavaDoc:

/**
 * Gets the field names that have signatures and are signed.
 *
 * @return the field names that have signatures and are signed
 */
public ArrayList<String> getSignatureNames()
like image 92
mkl Avatar answered Oct 12 '22 22:10

mkl


If you are using newer iText version like 5.5.x here is a full working example how you can check a digitally signed PDF (a lot of useful development and changes have been done in iText since version 2.1.7):

import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.security.PdfPKCS7;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.Principal;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DigitalSignatureCheck {

    private static final Logger LOGGER = LoggerFactory.getLogger(DigitalSignatureCheck.class);

    public static final boolean verifySignature(PdfReader pdfReader)
            throws GeneralSecurityException, IOException {
        boolean valid = false;
        AcroFields acroFields = pdfReader.getAcroFields();
        List<String> signatureNames = acroFields.getSignatureNames();
        if (!signatureNames.isEmpty()) {
            for (String name : signatureNames) {
                if (acroFields.signatureCoversWholeDocument(name)) {
                    PdfPKCS7 pkcs7 = acroFields.verifySignature(name);
                    valid = pkcs7.verify();
                    String reason = pkcs7.getReason();
                    Calendar signedAt = pkcs7.getSignDate();
                    X509Certificate signingCertificate = pkcs7.getSigningCertificate();
                    Principal issuerDN = signingCertificate.getIssuerDN();
                    Principal subjectDN = signingCertificate.getSubjectDN();
                    LOGGER.info("valid = {}, date = {}, reason = '{}', issuer = '{}', subject = '{}'",
                            valid, signedAt.getTime(), reason, issuerDN, subjectDN);
                    break;
                }
            }
        }
        return valid;
    }

    private static void validate(String name)
            throws IOException, GeneralSecurityException {
        InputStream is = DigitalSignatureCheck.class.getClassLoader()
                         .getResourceAsStream(name);
        PdfReader reader = new PdfReader(is);
        boolean ok = verifySignature(reader);
        LOGGER.info("'{}' is {}signed", name, ok ? "" : "NOT ");
    }

    public static void main(String[] args) throws Exception {
        validate("any.pdf"); // if placed in resources' root
    }
}

Using the LOGGER is just for displaying the result.

like image 32
Miklos Krivan Avatar answered Oct 13 '22 00:10

Miklos Krivan