Skip to main content
All docs
V25.1
  • How to: Validate a PDF Document Signature

    • 6 minutes to read

    Important

    You need a license for the DevExpress Office File API Subscription or DevExpress Universal Subscription to use these examples in production code.

    The PDF Document API allows you to validate PKCS #7 signatures in a PDF document. Use the PdfPkcs7Signature class methods to obtain information about the PKCS#7 signature and verify it.

    The following code snippet creates a console app that obtains the PKCS#7 signatures from a PDF document (Document.pdf in this example). Once the signature is obtained, the code checks attributes such as the time of signing, the signer’s identity, and authenticity of the signature. The result is shown in a console.

    using DevExpress.Pdf;
    // ...
    // Get the Document.pdf file.
    using (PdfDocumentSigner documentSigner = new PdfDocumentSigner("Document.pdf"))
        // Retrieve the list of `PdfSignatureInfo` objects in the document.
        foreach (var signature in documentSigner.GetSignatureInfo()) {
            Console.WriteLine("Signature field name : {0}", signature.FieldName);
            Console.WriteLine("  Signer name : {0}", signature.SignerName);
            // Obtain the PKCS#7 signature from the list of `PdfSignatureInfo` objects and verify it.
            var pkcs7 = documentSigner.GetPdfPkcs7Signature(signature.FieldName);
            Console.WriteLine("  Is signature valid? : {0}", pkcs7.VerifySignature());
            // Obtain the PKCS#7 signature certificate and verify the certificate info.
            var certificate = pkcs7.GetSignatureCertificate();
            Console.WriteLine("  Certificate issuer : {0}", certificate.IssuerName.Name);
            Console.WriteLine("  Is certificate valid? : {0}", certificate.Verify());
            var timestampDate = pkcs7.GetTimeStampDate();
            // Get a timestamp and verify the time of signing.
            Console.WriteLine("  Does signature include a timestamp? : {0}", timestampDate.HasValue);
            if(timestampDate.HasValue) {
                Console.WriteLine("  Timestamp : {0}", timestampDate);
                Console.WriteLine("  Is timestamp valid? : {0}", pkcs7.VerifyTimeStamp());
            }
        }
    

    The result is shown below:

    Signature field name : Signature1
      Signer name : DevExpress Demo
      Is signature valid? : True
      Certificate issuer : CN=DevExpress Demo
      Is certificate valid? : False
      Does signature include a timestamp? : False
    Signature field name : 9a1677be-7fa2-4429-8cb3-bea0c737ebf4
      Signer name : DevExpress Demo
      Is signature valid? : True
      Certificate issuer : CN=DevExpress Demo
      Is certificate valid? : False
      Does signature include a timestamp? : True
      Timestamp : 11/14/2023 8:02:57 AM
      Is timestamp valid? : True
    

    View Example: Blazor: Validate Document Signatures

    Check Certificate Revocation Based on CRL and OCSP Responses

    Call the PdfPkcs7Signature.CheckCertificateRevocation method to obtain information about signature certificate revocation based on Online Certificate Status Protocol (OCSP) and Certificate Revocation List (CRL) responses.

    The following code snippet checks the status of signature certificates in the “Signed_file.pdf” file:

    using DevExpress.Pdf;
    
    namespace ConsoleApp {
        internal class Program {
            static void Main(string[] args) {
                CheckCertificateRevocationInfo();
            }
            public static void CheckCertificateRevocationInfo() {
                using (PdfDocumentSigner documentSigner = new PdfDocumentSigner("Signed_file.pdf"))
                    // Retrieve the list of `PdfSignatureInfo` objects in the document.
                    foreach (var signature in documentSigner.GetSignatureInfo()){
                        Console.WriteLine("Signature field name : {0}", signature.FieldName);
                        Console.WriteLine("Signer name : {0}", signature.SignerName);
                        var pkcs7 = documentSigner.GetPdfPkcs7Signature(signature.FieldName);
                        Console.WriteLine("Is signature valid? : {0}", pkcs7.VerifySignature());
                        // Check wheter CRL/OCSP responses are embedded in the signature. If not, request them online.
                        Console.WriteLine("Is CRL embedded?: {0}", pkcs7.CrlList != null);
                        Console.WriteLine("Is OCSP embedded?: {0}", pkcs7.OcspList != null);
                        PdfRevocationVerificationOptions options = new PdfRevocationVerificationOptions(){
                            TryFetchCrlOnline = pkcs7.CrlList == null,
                            TryFetchOcspOnline = pkcs7.OcspList == null,
                        };
                        // Obtain information about signature certificate revocation.
                        var result = pkcs7.CheckCertificateRevocation(DateTime.UtcNow, options);
                        Console.WriteLine("Is certificate revoked?: {0}", result.IsCrlRevoked);
                        if (result.IsCrlRevoked)
                            Console.WriteLine("Is CRL found online?: {0}", result.IsCrlFoundOnline);
                        Console.WriteLine("OCSP Response Status: {0}", result.OcspRevocationStatus);
                        if (result.OcspRevocationStatus != PdfOcspRevocationStatus.None)
                            Console.WriteLine("Is OCSP found online?: {0}", result.IsOcspFoundOnline);
                        // Check whether the signature is a TimeStamp.
                        Console.WriteLine("Is Document Timestamp?: {0}", pkcs7.IsDocumentTimeStamp);
                        Console.WriteLine();
                    }
            }
    
        }
    }       
    

    The result is shown below:

    Signature field name : Signature1
    Signer name : DevExpress Demo
    Is signature valid? : True
    Is CRL embedded?: False
    Is OCSP embedded?: False
    Is certificate revoked?: False
    OCSP Response Status: Good
    Is OCSP found online: True
    Is Document Timestamp: False
    
    Signature field name : Signature1
    Signer name : DevExpress Demo
    Is signature valid? : True
    Is CRL embedded?: False
    Is OCSP embedded?: False
    Is certificate revoked?: False
    OCSP Response Status: Unknown
    Is OCSP found online: True
    Is Document Timestamp: True
    

    Validate Long Term Validation (LTV) Signatures

    Call the PdfDocumentSigner.VerifyLtv method to obtain Long Term Validation (LTV) records about the state of the signature certificate.

    The following example executes an LTV check for a signature from the “Signed_file.pdf” file:

    using DevExpress.Office.DigitalSignatures;
    
    namespace ConsoleApp {
        internal class Program {
            static void Main(string[] args) {
                VerifyLTV();
            }
            public static void VerifyLTV(){
                using (PdfDocumentSigner documentSigner = new PdfDocumentSigner("Signed_file.pdf")){
                    PdfLtvOptions options = new PdfLtvOptions(){
                        TryFetchCrlOnline = true,
                        TryFetchOcspOnline = true,
                        VerifyEntireCertificateChain = true,
                    };
                    var result = documentSigner.VerifyLtv(options);
                    foreach (var entry in result){
                        Console.WriteLine("Signature Name: {0}", entry.SignatureFieldName);
                        Console.WriteLine("Certificate in chain: {0}", entry.CertificateRevocationResults.Count);
                        foreach(var revocation in entry.CertificateRevocationResults){
                            Console.WriteLine("Certificate {0}", revocation.Key.Subject);
                            Console.WriteLine("Is certificate revoked?: {0}", revocation.Value.IsCrlRevoked);
                            if (revocation.Value.IsCrlRevoked)
                                Console.WriteLine("Is CRL found online?: {0}", revocation.Value.IsCrlFoundOnline);
                            Console.WriteLine("OCSP Response Status: {0}", revocation.Value.OcspRevocationStatus);
                            if (revocation.Value.OcspRevocationStatus != PdfOcspRevocationStatus.None)
                                Console.WriteLine("Is OCSP found online?: {0}", revocation.Value.IsOcspFoundOnline);
                            Console.WriteLine();
                        }
                    }
                }
            }
        }
    }