Back to Devexpress

How to: Validate a PDF Document Signature

officefileapi-404728-pdf-document-api-examples-document-protection-how-to-validate-a-pdf-document-signature.md

latest14.1 KB
Original Source

How to: Validate a PDF Document Signature

  • Apr 15, 2025
  • 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.

csharp
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());
        }
    }
vb
Imports System
Imports DevExpress.Pdf
' ...
Using documentSigner As New PdfDocumentSigner("Document.pdf")
    ' Retrieve the list of `PdfSignatureInfo` objects in the document.
    For Each 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.
        Dim pkcs7 = documentSigner.GetPdfPkcs7Signature(signature.FieldName)
        Console.WriteLine(" Is signature valid? : {0}", pkcs7.VerifySignature())
        ' Obtain the PKCS#7 signature certificate and verify the certificate info.
        Dim certificate = pkcs7.GetSignatureCertificate()
        Console.WriteLine(" Certificate issuer : {0}", certificate.IssuerName.Name)
        Console.WriteLine(" Is certificate valid? : {0}", certificate.Verify())
        Dim 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 Then
            Console.WriteLine(" Timestamp : {0}", timestampDate)
            Console.WriteLine(" Is timestamp valid? : {0}", pkcs7.VerifyTimeStamp())
        End If
    Next signature
End Using

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:

csharp
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();
                }
        }

    }
}
vb
Imports DevExpress.Pdf

Namespace ConsoleApp
    Friend Class Program

        Shared Sub Main(ByVal args() As String)
            CheckCertificateRevocationInfo()
        End Sub
        Public Shared Sub CheckCertificateRevocationInfo()
            Using documentSigner As New PdfDocumentSigner("Signed_file.pdf")
                ' Retrieve the list of `PdfSignatureInfo` objects in the document.
                For Each signature In documentSigner.GetSignatureInfo()
                    Console.WriteLine("Signature field name : {0}", signature.FieldName)
                    Console.WriteLine("Signer name : {0}", signature.SignerName)
                    Dim pkcs7 = documentSigner.GetPdfPkcs7Signature(signature.FieldName)
                    Console.WriteLine("Is signature valid? : {0}", pkcs7.VerifySignature())
                    ' Check whether CRL/OCSP responses are embedded in the signature. If not, request them online.
                    Console.WriteLine("Is CRL embedded?: {0}", pkcs7.CrlList IsNot Nothing)
                    Console.WriteLine("Is OCSP embedded?: {0}", pkcs7.OcspList IsNot Nothing)
                    Dim options As New PdfRevocationVerificationOptions() With {
                        .TryFetchCrlOnline = pkcs7.CrlList Is Nothing,
                        .TryFetchOcspOnline = pkcs7.OcspList Is Nothing
                    }
                    ' Obtain information about signature certificate revocation.
                    Dim result = pkcs7.CheckCertificateRevocation(Date.UtcNow, options)
                    Console.WriteLine("Is certificate revoked?: {0}", result.IsCrlRevoked)
                    If result.IsCrlRevoked Then
                        Console.WriteLine("Is CRL found online?: {0}", result.IsCrlFoundOnline)
                    End If
                    Console.WriteLine("OCSP Response Status: {0}", result.OcspRevocationStatus)
                    If result.OcspRevocationStatus <> PdfOcspRevocationStatus.None Then
                        Console.WriteLine("Is OCSP found online?: {0}", result.IsOcspFoundOnline)
                    End If
                    ' Check whether the signature is a TimeStamp.
                    Console.WriteLine("Is Document Timestamp?: {0}", pkcs7.IsDocumentTimeStamp)
                    Console.WriteLine()
                Next signature
            End Using
        End Sub
    End Class
End Namespace

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:

csharp
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();
                    }
                }
            }
        }
    }
}
vb
Imports DevExpress.Pdf

Namespace ConsoleApp
    Friend Class Program
        Shared Sub Main(ByVal args() As String) 
            VerifyLTV()
        End Sub
        Public Shared Sub VerifyLTV()
            Using documentSigner As New PdfDocumentSigner("Signed_file.pdf")
                Dim options As New PdfLtvOptions() With {
                    .TryFetchCrlOnline = True,
                    .TryFetchOcspOnline = True,
                    .VerifyEntireCertificateChain = True
                }
                Dim result = documentSigner.VerifyLtv(options)
                For Each entry In result
                    Console.WriteLine("Signature Name: {0}", entry.SignatureFieldName)
                    Console.WriteLine("Certificate in chain: {0}", entry.CertificateRevocationResults.Count)
                    For Each revocation In entry.CertificateRevocationResults
                        Console.WriteLine("Certificate {0}", revocation.Key.Subject)
                        Console.WriteLine("Is certificate revoked?: {0}", revocation.Value.IsCrlRevoked)
                        If revocation.Value.IsCrlRevoked Then
                            Console.WriteLine("Is CRL found online?: {0}", revocation.Value.IsCrlFoundOnline)
                        End If
                        Console.WriteLine("OCSP Response Status: {0}", revocation.Value.OcspRevocationStatus)
                        If revocation.Value.OcspRevocationStatus <> PdfOcspRevocationStatus.None Then
                            Console.WriteLine("Is OCSP found online?: {0}", revocation.Value.IsOcspFoundOnline)
                        End If
                        Console.WriteLine()
                    Next revocation
                Next entry
            End Using
        End Sub
    End Class
End Namespace