VintaSoft Imaging .NET SDK 12.3: Documentation for .NET developer
In This Topic
    PDF: Usage of digital signatures in PDF document
    In This Topic
    Digital signature is used for authenticating the identity of a user and the validity of the document contents.
    The SDK allows to:

    Add digital signature to PDF document

    To sign a PDF document using digital signature is necessary to do the following:

    Here is an example, that demonstrates how to sign a PDF document via digital signature:
    /// <summary>
    /// Signs a PDF or PDF/A document using specified certificate.
    /// </summary>
    /// <param name="inputFilename">The filename of input PDF document.</param>
    /// <param name="outputFilename">The filename of output PDF document.</param>
    /// <param name="certificate">The certificate that should be used
    /// for signing the input PDF document.</param>
    /// <param name="conformance">The conformance of PDF document.</param>
    public static void SignDocument(
        string inputFilename,
        string outputFilename,
        Vintasoft.Imaging.Pdf.PdfDocumentConformance conformance,
        System.Security.Cryptography.X509Certificates.X509Certificate2 certificate)
    {
        SignDocument(inputFilename, outputFilename, conformance, certificate, false, null);
    }
    
    /// <summary>
    /// Signs with timestamp a PDF or PDF/A document using specified certificate.
    /// </summary>
    /// <param name="inputFilename">The filename of input PDF document.</param>
    /// <param name="outputFilename">The filename of output PDF document.</param>
    /// <param name="certificate">The certificate that should be used
    /// for signing the input PDF document.</param>
    /// <param name="addCertificateChain">A value indicating whether signing certificate chain must be added to signature.</param>
    /// <param name="conformance">The conformance of PDF document.</param>
    /// <param name="timestampServerUrl">Timestamp server URL.</param>
    public static void SignDocument(
        string inputFilename,
        string outputFilename,
        Vintasoft.Imaging.Pdf.PdfDocumentConformance conformance,
        System.Security.Cryptography.X509Certificates.X509Certificate2 certificate,
        bool addCertificateChain,
        string timestampServerUrl)
    {
        Vintasoft.Imaging.Pdf.Processing.PdfDocumentConverter converter = null;
    
        // if PDF document conformance is specified
        if (conformance != Vintasoft.Imaging.Pdf.PdfDocumentConformance.Undefined)
        {
            // create PDF document converter
            converter = Vintasoft.Imaging.Pdf.Processing.PdfDocumentConverter.Create(conformance);
    
            // if is PDF/A converter
            Vintasoft.Imaging.Pdf.Processing.PdfA.PdfAConverter pdfAConverter = converter as Vintasoft.Imaging.Pdf.Processing.PdfA.PdfAConverter;
            if (pdfAConverter != null)
            {
                // set ICC profiles
                //pdfAConverter.DefaultCmykIccProfileFilename = "DefaultCMYK.icc";
                //pdfAConverter.DefaultRgbIccProfileFilename = "DefaultRGB.icc";
            }
    
            // if PDF document converter is not found
            if (converter == null)
            {
                string message = string.Format("Unsupported {0} conformance.", conformance);
                throw new System.ArgumentOutOfRangeException(message);
            }
        }
    
        // open PDF document
        using (Vintasoft.Imaging.Pdf.PdfDocument document = new Vintasoft.Imaging.Pdf.PdfDocument(inputFilename))
        {
            // add signature
            AddSignature(document, certificate, addCertificateChain, timestampServerUrl, 1);
    
            // if PDF document cannot be converted
            if (converter == null)
            {
                if (inputFilename == outputFilename)
                {
                    // sign PDF document and save changes in PDF document
                    document.SaveChanges();
                }
                else
                {
                    // sign PDF document and save PDF document to the output file
                    document.SaveChanges(outputFilename);
                }
            }
            else
            {
                if (inputFilename != outputFilename)
                {
                    Vintasoft.Imaging.Pdf.Processing.PdfA.PdfAConverter pdfAConverter =
                        (Vintasoft.Imaging.Pdf.Processing.PdfA.PdfAConverter)converter;
                    pdfAConverter.OutputFilename = outputFilename;
                }
    
                // sign and convert PDF document
                Vintasoft.Imaging.Processing.ConversionProfileResult conversionResult =
                    converter.Convert(document, new Vintasoft.Imaging.Processing.ProcessingState());
    
                // if conversion falied
                if (!conversionResult.IsSuccessful)
                {
                    // throw conversion exception
                    throw conversionResult.CreateConversionException();
                }
            }
        }
    }
    
    /// <summary>
    /// Adds a digital signature to specified PDF document.
    /// </summary>
    /// <param name="document">The PDF document.</param>
    /// <param name="certificate">The certificate that should be added.</param>
    /// <param name="timestampServerUrl">Timestamp server URL.</param>
    /// <param name="addCertificateChain">A value indicating whether signing certificate chain must be added to signature.</param>
    /// <param name="sigNumber">The number of signature field.</param>
    private static void AddSignature(
        Vintasoft.Imaging.Pdf.PdfDocument document,
        System.Security.Cryptography.X509Certificates.X509Certificate2 certificate,
        bool addCertificateChain,
        string timestampServerUrl,
        int sigNumber)
    {
        // if PDF document does not have interactive form
        if (document.InteractiveForm == null)
        {
            // create the interactive form in document
            document.InteractiveForm = new Vintasoft.Imaging.Pdf.Tree.InteractiveForms.PdfDocumentInteractiveForm(document);
        }
    
        // specify that document contains signatures
        document.InteractiveForm.SignatureFlags =
            Vintasoft.Imaging.Pdf.Tree.InteractiveForms.PdfDocumentSignatureFlags.SignaturesExist |
            Vintasoft.Imaging.Pdf.Tree.InteractiveForms.PdfDocumentSignatureFlags.AppendOnly;
    
        // specify that the viewer application must NOT construct appearance streams and
        // appearance properties for widget annotations in the document
        document.InteractiveForm.NeedAppearances = false;
    
        // get PDF page on which signature will be placed
        Vintasoft.Imaging.Pdf.Tree.PdfPage page = document.Pages[0];
    
        // calculate the signature field rectangle (field will be placed in the bottom-center of page)
        System.Drawing.RectangleF signatureRect = new System.Drawing.RectangleF();
        signatureRect.Width = page.MediaBox.Width / 5;
        signatureRect.Height = signatureRect.Width / 3;
        signatureRect.X = page.MediaBox.X + (page.MediaBox.Width - signatureRect.Width) / 2;
        signatureRect.Y = page.MediaBox.Y + signatureRect.Height * sigNumber;
    
        // create parameters for creation of PKCS#7 signature
        Vintasoft.Imaging.Pdf.Tree.DigitalSignatures.PdfPkcsSignatureCreationParams creationParams =
            new Vintasoft.Imaging.Pdf.Tree.DigitalSignatures.PdfPkcsSignatureCreationParams(certificate, addCertificateChain);
        // if timestamp server is specified
        if (!string.IsNullOrEmpty(timestampServerUrl))
        {
            // specify the timestamp authority client
            creationParams.TimestampAuthorityClient = new Vintasoft.Imaging.Pdf.Tree.DigitalSignatures.TimestampAuthorityWebClient(timestampServerUrl);
        }
    
        // create PKCS#7 signature
        Vintasoft.Imaging.Pdf.Tree.DigitalSignatures.PdfPkcsSignature signature = Vintasoft.Imaging.Pdf.Tree.DigitalSignatures.PdfPkcsSignature.CreatePkcs7Signature(
             document.Format, creationParams);
    
        // create signature info
        Vintasoft.Imaging.Pdf.Tree.DigitalSignatures.PdfSignatureInformation signatureInfo =
            new Vintasoft.Imaging.Pdf.Tree.DigitalSignatures.PdfSignatureInformation(document, signature);
        signatureInfo.SignerName = certificate.GetNameInfo(
            System.Security.Cryptography.X509Certificates.X509NameType.SimpleName, false);
        signatureInfo.Reason = "Test signing";
        signatureInfo.Location = System.Globalization.CultureInfo.CurrentCulture.EnglishName;
        signatureInfo.SigningTime = System.DateTime.Now;
    
        // create the signature field
        Vintasoft.Imaging.Pdf.Tree.InteractiveForms.PdfInteractiveFormSignatureField signatureField =
            new Vintasoft.Imaging.Pdf.Tree.InteractiveForms.PdfInteractiveFormSignatureField(document, string.Format("MySignature{0}", sigNumber), signatureRect);
    
        // set the signature information
        signatureField.SignatureInfo = signatureInfo;
    
        // create the signature appearance
        using (Vintasoft.Imaging.Pdf.Drawing.PdfGraphics g = signatureField.CreateAppearanceGraphics())
        {
            // signature text
            string signatureText = string.Format("Digitally signed by\n{0}",
                signatureInfo.SignerName);
    
            // signature appearance rect
            System.Drawing.RectangleF rect = new System.Drawing.RectangleF(
                System.Drawing.PointF.Empty,
                signatureField.Annotation.Rectangle.Size);
    
            // draw background
            g.FillRectangle(new Vintasoft.Imaging.Pdf.Drawing.PdfBrush(
                System.Drawing.Color.FromArgb(255, System.Drawing.Color.Lime)), rect);
    
            // padding
            rect.Inflate(-rect.Height / 10, -rect.Height / 10);
    
            // create TimesRoman font
            Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont font = document.FontManager.GetStandardFont(
                Vintasoft.Imaging.Pdf.Tree.Fonts.PdfStandardFontType.TimesRoman);
    
            // measure font size
            float fontSize = g.MeasureFontSize(signatureText, font, rect.Width, rect.Height);
    
            // draw signture text
            g.DrawString(
                signatureText,
                font, fontSize, new Vintasoft.Imaging.Pdf.Drawing.PdfBrush(System.Drawing.Color.Black),
                rect, Vintasoft.Imaging.Pdf.Drawing.PdfContentAlignment.Center, false);
        }
    
        // add signature field to the interactive form of document
        document.InteractiveForm.Fields.Add(signatureField);
    
        // if PDF page does not have annotations
        if (page.Annotations == null)
            // create an empty annotation collection for page
            page.Annotations = new Vintasoft.Imaging.Pdf.Tree.Annotations.PdfAnnotationList(document);
        // add widget annotation of signature field to the annotation collection of page
        page.Annotations.Add(signatureField.Annotation);
    }
    
    ''' <summary>
    ''' Signs a PDF or PDF/A document using specified certificate.
    ''' </summary>
    ''' <param name="inputFilename">The filename of input PDF document.</param>
    ''' <param name="outputFilename">The filename of output PDF document.</param>
    ''' <param name="certificate">The certificate that should be used
    ''' for signing the input PDF document.</param>
    ''' <param name="conformance">The conformance of PDF document.</param>
    Public Shared Sub SignDocument(inputFilename As String, outputFilename As String, conformance As Vintasoft.Imaging.Pdf.PdfDocumentConformance, certificate As System.Security.Cryptography.X509Certificates.X509Certificate2)
        SignDocument(inputFilename, outputFilename, conformance, certificate, False, Nothing)
    End Sub
    
    ''' <summary>
    ''' Signs with timestamp a PDF or PDF/A document using specified certificate.
    ''' </summary>
    ''' <param name="inputFilename">The filename of input PDF document.</param>
    ''' <param name="outputFilename">The filename of output PDF document.</param>
    ''' <param name="certificate">The certificate that should be used
    ''' for signing the input PDF document.</param>
    ''' <param name="addCertificateChain">A value indicating whether signing certificate chain must be added to signature.</param>
    ''' <param name="conformance">The conformance of PDF document.</param>
    ''' <param name="timestampServerUrl">Timestamp server URL.</param>
    Public Shared Sub SignDocument(inputFilename As String, outputFilename As String, conformance As Vintasoft.Imaging.Pdf.PdfDocumentConformance, certificate As System.Security.Cryptography.X509Certificates.X509Certificate2, addCertificateChain As Boolean, timestampServerUrl As String)
        Dim converter As Vintasoft.Imaging.Pdf.Processing.PdfDocumentConverter = Nothing
    
        ' if PDF document conformance is specified
        If conformance <> Vintasoft.Imaging.Pdf.PdfDocumentConformance.Undefined Then
            ' create PDF document converter
            converter = Vintasoft.Imaging.Pdf.Processing.PdfDocumentConverter.Create(conformance)
    
            ' if is PDF/A converter
            Dim pdfAConverter As Vintasoft.Imaging.Pdf.Processing.PdfA.PdfAConverter = TryCast(converter, Vintasoft.Imaging.Pdf.Processing.PdfA.PdfAConverter)
                    ' set ICC profiles
                    'pdfAConverter.DefaultCmykIccProfileFilename = "DefaultCMYK.icc";
                    'pdfAConverter.DefaultRgbIccProfileFilename = "DefaultRGB.icc";
            If pdfAConverter IsNot Nothing Then
            End If
    
            ' if PDF document converter is not found
            If converter Is Nothing Then
                Dim message As String = String.Format("Unsupported {0} conformance.", conformance)
                Throw New System.ArgumentOutOfRangeException(message)
            End If
        End If
    
        ' open PDF document
        Using document As New Vintasoft.Imaging.Pdf.PdfDocument(inputFilename)
            ' add signature
            AddSignature(document, certificate, addCertificateChain, timestampServerUrl, 1)
    
            ' if PDF document cannot be converted
            If converter Is Nothing Then
                If inputFilename = outputFilename Then
                    ' sign PDF document and save changes in PDF document
                    document.SaveChanges()
                Else
                    ' sign PDF document and save PDF document to the output file
                    document.SaveChanges(outputFilename)
                End If
            Else
                If inputFilename <> outputFilename Then
                    Dim pdfAConverter As Vintasoft.Imaging.Pdf.Processing.PdfA.PdfAConverter = DirectCast(converter, Vintasoft.Imaging.Pdf.Processing.PdfA.PdfAConverter)
                    pdfAConverter.OutputFilename = outputFilename
                End If
    
                ' sign and convert PDF document
                Dim conversionResult As Vintasoft.Imaging.Processing.ConversionProfileResult = converter.Convert(document, New Vintasoft.Imaging.Processing.ProcessingState())
    
                ' if conversion falied
                If Not conversionResult.IsSuccessful Then
                    ' throw conversion exception
                    Throw conversionResult.CreateConversionException()
                End If
            End If
        End Using
    End Sub
    
    ''' <summary>
    ''' Adds a digital signature to specified PDF document.
    ''' </summary>
    ''' <param name="document">The PDF document.</param>
    ''' <param name="certificate">The certificate that should be added.</param>
    ''' <param name="timestampServerUrl">Timestamp server URL.</param>
    ''' <param name="addCertificateChain">A value indicating whether signing certificate chain must be added to signature.</param>
    ''' <param name="sigNumber">The number of signature field.</param>
    Private Shared Sub AddSignature(document As Vintasoft.Imaging.Pdf.PdfDocument, certificate As System.Security.Cryptography.X509Certificates.X509Certificate2, addCertificateChain As Boolean, timestampServerUrl As String, sigNumber As Integer)
        ' if PDF document does not have interactive form
        If document.InteractiveForm Is Nothing Then
            ' create the interactive form in document
            document.InteractiveForm = New Vintasoft.Imaging.Pdf.Tree.InteractiveForms.PdfDocumentInteractiveForm(document)
        End If
    
        ' specify that document contains signatures
        document.InteractiveForm.SignatureFlags = Vintasoft.Imaging.Pdf.Tree.InteractiveForms.PdfDocumentSignatureFlags.SignaturesExist Or Vintasoft.Imaging.Pdf.Tree.InteractiveForms.PdfDocumentSignatureFlags.AppendOnly
    
        ' specify that the viewer application must NOT construct appearance streams and
        ' appearance properties for widget annotations in the document
        document.InteractiveForm.NeedAppearances = False
    
        ' get PDF page on which signature will be placed
        Dim page As Vintasoft.Imaging.Pdf.Tree.PdfPage = document.Pages(0)
    
        ' calculate the signature field rectangle (field will be placed in the bottom-center of page)
        Dim signatureRect As New System.Drawing.RectangleF()
        signatureRect.Width = page.MediaBox.Width / 5
        signatureRect.Height = signatureRect.Width / 3
        signatureRect.X = page.MediaBox.X + (page.MediaBox.Width - signatureRect.Width) / 2
        signatureRect.Y = page.MediaBox.Y + signatureRect.Height * sigNumber
    
        ' create parameters for creation of PKCS#7 signature
        Dim creationParams As New Vintasoft.Imaging.Pdf.Tree.DigitalSignatures.PdfPkcsSignatureCreationParams(certificate, addCertificateChain)
        ' if timestamp server is specified
        If Not String.IsNullOrEmpty(timestampServerUrl) Then
            ' specify the timestamp authority client
            creationParams.TimestampAuthorityClient = New Vintasoft.Imaging.Pdf.Tree.DigitalSignatures.TimestampAuthorityWebClient(timestampServerUrl)
        End If
    
        ' create PKCS#7 signature
        Dim signature As Vintasoft.Imaging.Pdf.Tree.DigitalSignatures.PdfPkcsSignature = Vintasoft.Imaging.Pdf.Tree.DigitalSignatures.PdfPkcsSignature.CreatePkcs7Signature(document.Format, creationParams)
    
        ' create signature info
        Dim signatureInfo As New Vintasoft.Imaging.Pdf.Tree.DigitalSignatures.PdfSignatureInformation(document, signature)
        signatureInfo.SignerName = certificate.GetNameInfo(System.Security.Cryptography.X509Certificates.X509NameType.SimpleName, False)
        signatureInfo.Reason = "Test signing"
        signatureInfo.Location = System.Globalization.CultureInfo.CurrentCulture.EnglishName
        signatureInfo.SigningTime = System.DateTime.Now
    
        ' create the signature field
        Dim signatureField As New Vintasoft.Imaging.Pdf.Tree.InteractiveForms.PdfInteractiveFormSignatureField(document, String.Format("MySignature{0}", sigNumber), signatureRect)
    
        ' set the signature information
        signatureField.SignatureInfo = signatureInfo
    
        ' create the signature appearance
        Using g As Vintasoft.Imaging.Pdf.Drawing.PdfGraphics = signatureField.CreateAppearanceGraphics()
            ' signature text
            Dim signatureText As String = String.Format("Digitally signed by" & vbLf & "{0}", signatureInfo.SignerName)
    
            ' signature appearance rect
            Dim rect As New System.Drawing.RectangleF(System.Drawing.PointF.Empty, signatureField.Annotation.Rectangle.Size)
    
            ' draw background
            g.FillRectangle(New Vintasoft.Imaging.Pdf.Drawing.PdfBrush(System.Drawing.Color.FromArgb(255, System.Drawing.Color.Lime)), rect)
    
            ' padding
            rect.Inflate(-rect.Height / 10, -rect.Height / 10)
    
            ' create TimesRoman font
            Dim font As Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont = document.FontManager.GetStandardFont(Vintasoft.Imaging.Pdf.Tree.Fonts.PdfStandardFontType.TimesRoman)
    
            ' measure font size
            Dim fontSize As Single = g.MeasureFontSize(signatureText, font, rect.Width, rect.Height)
    
            ' draw signture text
            g.DrawString(signatureText, font, fontSize, New Vintasoft.Imaging.Pdf.Drawing.PdfBrush(System.Drawing.Color.Black), rect, Vintasoft.Imaging.Pdf.Drawing.PdfContentAlignment.Center, _
                False)
        End Using
    
        ' add signature field to the interactive form of document
        document.InteractiveForm.Fields.Add(signatureField)
    
        ' if PDF page does not have annotations
        If page.Annotations Is Nothing Then
            ' create an empty annotation collection for page
            page.Annotations = New Vintasoft.Imaging.Pdf.Tree.Annotations.PdfAnnotationList(document)
        End If
        ' add widget annotation of signature field to the annotation collection of page
        page.Annotations.Add(signatureField.Annotation)
    End Sub
    


    Verify digital signature

    To verify the signature of PDF document is necessary to do the following:

    Here is an example, that demonstrates how to check whether signature of PDF document is authentic:
    /// <summary>
    /// Displays and verifies signatures of PDF document.
    /// </summary>
    /// <param name="pdfFilename">The filename of PDF document.</param>
    public static void VerifyDocumentSignatures(string pdfFilename)
    {
        // open PDF document
        using (Vintasoft.Imaging.Pdf.PdfDocument document = 
            new Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename))
        {
            // if document does not have interactive form
            if (document.InteractiveForm == null)
            {
                System.Console.WriteLine("Signature fields are not found.");
                return;
            }
    
            // get an array of signature fields of document
            Vintasoft.Imaging.Pdf.Tree.InteractiveForms.PdfInteractiveFormSignatureField[] signatureFields =
                document.InteractiveForm.GetSignatureFields();
            // if document does not have signature fields
            if (signatureFields.Length == 0)
            {
                System.Console.WriteLine("Signture fields are not found.");
                return;
            }
    
            // for each signature field
            for (int i = 0; i < signatureFields.Length; i++)
            {
                // get reference to the signature field
                Vintasoft.Imaging.Pdf.Tree.InteractiveForms.PdfInteractiveFormSignatureField signatureField = signatureFields[i];
                // print signature field name
                System.Console.WriteLine(string.Format("[{0}]Signaure field: {1}", i + 1, signatureField.FullyQualifiedName));
    
                // get information about signature
                Vintasoft.Imaging.Pdf.Tree.DigitalSignatures.PdfSignatureInformation signatureInfo = signatureField.SignatureInfo;
                // if signature information is empty
                if (signatureInfo == null)
                {
                    System.Console.WriteLine("Empty signature field.");
                }
                // if signature information is NOT empty
                else
                {
                    // check is document timestamp signature
                    if (signatureInfo.IsTimeStamp)
                        System.Console.WriteLine("Signature is a document timestamp signature");
    
                    // print signature filter
                    System.Console.WriteLine(string.Format("Filter      : {0} ({1})", signatureInfo.Filter, signatureInfo.SubFilter));
                    // print the signer name
                    if (signatureInfo.SignerName != null)
                        System.Console.WriteLine(string.Format("Signed by   : {0}", signatureInfo.SignerName));
                    // print the signature reason
                    if (signatureInfo.Reason != null)
                        System.Console.WriteLine(string.Format("Reason      : {0}", signatureInfo.Reason));
                    // print the signature location
                    if (signatureInfo.Location != null)
                        System.Console.WriteLine(string.Format("Location    : {0}", signatureInfo.Location));
                    // print the signer contact info
                    if (signatureInfo.ContactInfo != null)
                        System.Console.WriteLine(string.Format("Contact Info: {0}", signatureInfo.SignerName));
                    // print the signing date
                    if (signatureInfo.SigningTime != System.DateTime.MinValue)
                        System.Console.WriteLine(string.Format("Signig Date : {0}", signatureInfo.SigningTime.ToString("f")));
    
                    // get PKCS signature
                    bool error = false;
                    Vintasoft.Imaging.Pdf.Tree.DigitalSignatures.PdfPkcsSignature signature = null;
                    try
                    {
                        signature = signatureInfo.GetSignature();
                    }
                    catch (System.Exception e)
                    {
                        error = true;
                        System.Console.WriteLine("PKCS signature parsing error: {0}", e.Message);
                    }
                    if (error)
                        continue;
    
                    // print name of signature algorithm
                    System.Console.WriteLine(string.Format("Algorithm   : {0}", signature.SignatureAlgorithmName));
    
                    // print information about signature certificate chain
                    System.Console.WriteLine("Sign certificate chain:");
                    System.Security.Cryptography.X509Certificates.X509Certificate2[] signCertChain = 
                        signature.SigningCertificateChain;
                    string padding = "";
                    foreach (System.Security.Cryptography.X509Certificates.X509Certificate2 cert in signCertChain)
                    {
                        padding += "    ";
                        System.Console.WriteLine("{0}Serial number: {1}", padding, cert.SerialNumber);
                        System.Console.WriteLine("{0}Issuer       : {1}", padding, cert.GetNameInfo(
                            System.Security.Cryptography.X509Certificates.X509NameType.SimpleName, true));
                        System.Console.WriteLine("{0}Subject      : {1}", padding, cert.GetNameInfo(
                            System.Security.Cryptography.X509Certificates.X509NameType.SimpleName, false));
                    }
    
    
                    // verify digital signature
                    VerifyDigitalSignature(signatureInfo, signature);
                }
                System.Console.WriteLine();
            }
        }
    }
    
    /// <summary>
    /// Verifies the digital signature.
    /// </summary>
    /// <param name="signature">The signature.</param>
    /// <param name="signatureInfo">The signature information.</param>
    /// <returns><b>true</b> if signature is valid; otherwise, <b>false</b>.</returns>
    public static bool VerifyDigitalSignature(
        Vintasoft.Imaging.Pdf.Tree.DigitalSignatures.PdfSignatureInformation signatureInfo,
        Vintasoft.Imaging.Pdf.Tree.DigitalSignatures.PdfPkcsSignature signature)
    {
        System.Console.WriteLine("Verifying signature...");
    
        bool signatureVerifyResult = false;
        bool embeddedTimestampVerifyResult = false;
        bool certificateVerifyResult = false;
        bool embeddedTimestampCertificateVerifyResult = false;
        bool signatureCoversWholeDocument = false;
        System.Security.Cryptography.X509Certificates.X509Chain certificateChain = null;
        System.Security.Cryptography.X509Certificates.X509Chain timestampCertificateChain = null;
    
    
        // verify signature
    
        try
        {
            // check that signature covers the whole document
            signatureCoversWholeDocument = signatureInfo.SignatureCoversWholeDocument();
    
            // verify PKCS signature
            signatureVerifyResult = signature.VerifySignature();
    
            // if signature has embedded timestamp
            if (signature.HasEmbeddedTimeStamp)
            {
                // verify embedded timestamp
                embeddedTimestampVerifyResult = signature.VerifyTimestamp();
            }
    
            // build and verify certificate chain
            certificateChain = new System.Security.Cryptography.X509Certificates.X509Chain();
            certificateVerifyResult = certificateChain.Build(signature.SigningCertificate);
    
            // if signature has embedded timestamp
            if (signature.HasEmbeddedTimeStamp)
            {
                // build and verify timestamp certificate chain
                timestampCertificateChain = new System.Security.Cryptography.X509Certificates.X509Chain();
                embeddedTimestampCertificateVerifyResult = certificateChain.Build(signature.TimestampCertificate);
            }
    
        }
        catch (System.Exception verificationException)
        {
            System.Console.WriteLine("Verification failed: {0}", verificationException.Message);
            return false;
        }
    
        bool pageContentModified = false;
        string subsequentChangesMessage = "";
        // if PKCS signature verification is passed AND signature does not cover the whole document
        if (signatureVerifyResult && !signatureCoversWholeDocument)
        {
            try
            {
                // if signature has revision info
                if (signatureInfo.SignedRevision != null)
                {
                    // check subsequent changes
                    using (Vintasoft.Imaging.Pdf.PdfDocumentRevisionComparer documentChanges = signatureInfo.GetDocumentChanges())
                    {
                        // check subsequent changes in pages content
                        pageContentModified = documentChanges.HasModifiedPages;
    
                        // build subsequent changes message
                        if (documentChanges.ChangedPageContents.Count > 0)
                            subsequentChangesMessage += string.Format("{0} page(s) modified; ", documentChanges.ChangedPageContents.Count);
                        if (documentChanges.AddedPages.Count > 0)
                            subsequentChangesMessage += string.Format("{0} page(s) added; ", documentChanges.AddedPages.Count);
                        if (documentChanges.RemovedPages.Count > 0)
                            subsequentChangesMessage += string.Format("{0} page(s) removed; ", documentChanges.RemovedPages.Count);
                        if (documentChanges.RemovedAnnotations.Count > 0)
                            subsequentChangesMessage += string.Format("annotations(s) on {0} page(s) removed; ", documentChanges.RemovedAnnotations.Count);
                        if (documentChanges.RemovedAnnotations.Count > 0)
                            subsequentChangesMessage += string.Format("removed annotation(s) on {0} page(s); ", documentChanges.RemovedAnnotations.Count);
                        if (documentChanges.AddedAnnotations.Count > 0)
                            subsequentChangesMessage += string.Format("added annotation(s) on {0} page(s); ", documentChanges.AddedAnnotations.Count);
                        if (documentChanges.ChangedAnnotations.Count > 0)
                            subsequentChangesMessage += string.Format("changed annotation(s) on {0} page(s); ", documentChanges.ChangedAnnotations.Count);
                        if (documentChanges.MiscellaneousChanges.Count > 0)
                            subsequentChangesMessage += string.Format("miscellaneous changes: {0}; ", documentChanges.MiscellaneousChanges.Count);
                    }
                }
            }
            catch (System.Exception verificationException)
            {
                System.Console.WriteLine("Verification failed: {0}", verificationException.Message);
                return false;
            }
        }
    
        // print signature verification result
    
        // if PKCS signature verification is failed OR
        // signature does not cover the whole document AND page(s) content is modified
        if (!signatureVerifyResult || (!signatureCoversWholeDocument && pageContentModified))
            System.Console.WriteLine("Signature is INVALID.");
        // if certificate verification is failed
        else if (!certificateVerifyResult || (signature.HasEmbeddedTimeStamp && (!embeddedTimestampCertificateVerifyResult || !embeddedTimestampVerifyResult)))
            System.Console.WriteLine("Signature validity is UNKNOWN.");
        else
            System.Console.WriteLine("Signature is VALID.");
    
    
        // print signature verification details
    
        // if signature verification is successful
        if (signatureVerifyResult)
        {
            // if signature covers the whole document
            if (signatureCoversWholeDocument)
            {
                System.Console.WriteLine("    Signature verification: Document has not been modified since this signature was applied.");
            }
            // if signature does NOT cover the whole document
            else
            {
                if (pageContentModified)
                {
                    System.Console.WriteLine("    Signature verification: Document has been modified or corrupted since it was signed.");
                    System.Console.WriteLine(string.Format("    Subsequent changes: {0}.", subsequentChangesMessage));
                }
                else if (subsequentChangesMessage != "")
                {
                    System.Console.WriteLine("    Signature verification: The revision of the document that was covered by this signature has not been altered; however, there have been subsequent changes to the document.");
                    System.Console.WriteLine(string.Format("    Subsequent changes: {0}.", subsequentChangesMessage));
                }
                else
                {
                    System.Console.WriteLine("    Signature verification: Document has not been modified since this signature was applied.");
                }
            }
        }
        // if signature verification is NOT successful
        else
        {
            System.Console.WriteLine("    Signature verification: Document has been modified or corrupted since it was signed.");
        }
    
        // if signature has embedded timestamp
        if (signature.HasEmbeddedTimeStamp)
        {
            if (embeddedTimestampVerifyResult)
                System.Console.WriteLine("    Timestamp verification: Timestamp is valid.");
            else
                System.Console.WriteLine("    Timestamp verification: Timestamp is valid.");
        }
    
    
        // print certificate verification details
    
        // if certificate chain is present
        if (certificateChain != null)
        {
            // if certificate verification is successful
            if (certificateVerifyResult)
            {
                System.Console.WriteLine("    Certificate verification: Signer's certificate is valid.");
            }
            // if certificate verification is NOT successful
            else
            {
                // print certificate verification status
                System.Console.WriteLine("    Certificate verification: Signer's certificate is invalid:");
                foreach (System.Security.Cryptography.X509Certificates.X509ChainStatus status in certificateChain.ChainStatus)
                    System.Console.Write(string.Format("        {0}: {1}", status.Status, status.StatusInformation));
            }
        }
    
        // if timestamp certificate chain is present
        if (timestampCertificateChain != null)
        {
            // if timestamp certificate verification is successful
            if (embeddedTimestampCertificateVerifyResult)
            {
                System.Console.WriteLine("    Timestamp certificate verification: Signer's certificate is valid.");
            }
            // if timestamp certificate verification is NOT successful
            else
            {
                // print certificate verification status
                System.Console.WriteLine("    Timestamp certificate verification: Signer's certificate is invalid:");
                foreach (System.Security.Cryptography.X509Certificates.X509ChainStatus status in timestampCertificateChain.ChainStatus)
                    System.Console.Write(string.Format("        {0}: {1}", status.Status, status.StatusInformation));
            }
        }
    
        // if signature is not verified
        if (!signatureVerifyResult)
            return false;
    
        // if signature does NOT cover the whole document and page content was modified
        if (!signatureCoversWholeDocument && pageContentModified)
            return false;
    
        // if signature certificate is NOT verified
        if (!certificateVerifyResult)
            return false;
        
        if (signature.HasEmbeddedTimeStamp)
        {
            // if timestamp is NOT verified
            if (!embeddedTimestampVerifyResult)
                return false;
    
            // if timestamp certifiacet is NOT verified
            if (!embeddedTimestampCertificateVerifyResult)
                return false;
        }
    
        // sigature is VALID
        return true;
    }
    
    ''' <summary>
    ''' Displays and verifies signatures of PDF document.
    ''' </summary>
    ''' <param name="pdfFilename">The filename of PDF document.</param>
    Public Shared Sub VerifyDocumentSignatures(pdfFilename As String)
        ' open PDF document
        Using document As New Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename)
            ' if document does not have interactive form
            If document.InteractiveForm Is Nothing Then
                System.Console.WriteLine("Signature fields are not found.")
                Return
            End If
    
            ' get an array of signature fields of document
            Dim signatureFields As Vintasoft.Imaging.Pdf.Tree.InteractiveForms.PdfInteractiveFormSignatureField() = document.InteractiveForm.GetSignatureFields()
            ' if document does not have signature fields
            If signatureFields.Length = 0 Then
                System.Console.WriteLine("Signture fields are not found.")
                Return
            End If
    
            ' for each signature field
            For i As Integer = 0 To signatureFields.Length - 1
                ' get reference to the signature field
                Dim signatureField As Vintasoft.Imaging.Pdf.Tree.InteractiveForms.PdfInteractiveFormSignatureField = signatureFields(i)
                ' print signature field name
                System.Console.WriteLine(String.Format("[{0}]Signaure field: {1}", i + 1, signatureField.FullyQualifiedName))
    
                ' get information about signature
                Dim signatureInfo As Vintasoft.Imaging.Pdf.Tree.DigitalSignatures.PdfSignatureInformation = signatureField.SignatureInfo
                ' if signature information is empty
                If signatureInfo Is Nothing Then
                    System.Console.WriteLine("Empty signature field.")
                Else
                    ' if signature information is NOT empty
                    ' check is document timestamp signature
                    If signatureInfo.IsTimeStamp Then
                        System.Console.WriteLine("Signature is a document timestamp signature")
                    End If
    
                    ' print signature filter
                    System.Console.WriteLine(String.Format("Filter      : {0} ({1})", signatureInfo.Filter, signatureInfo.SubFilter))
                    ' print the signer name
                    If signatureInfo.SignerName IsNot Nothing Then
                        System.Console.WriteLine(String.Format("Signed by   : {0}", signatureInfo.SignerName))
                    End If
                    ' print the signature reason
                    If signatureInfo.Reason IsNot Nothing Then
                        System.Console.WriteLine(String.Format("Reason      : {0}", signatureInfo.Reason))
                    End If
                    ' print the signature location
                    If signatureInfo.Location IsNot Nothing Then
                        System.Console.WriteLine(String.Format("Location    : {0}", signatureInfo.Location))
                    End If
                    ' print the signer contact info
                    If signatureInfo.ContactInfo IsNot Nothing Then
                        System.Console.WriteLine(String.Format("Contact Info: {0}", signatureInfo.SignerName))
                    End If
                    ' print the signing date
                    If signatureInfo.SigningTime <> System.DateTime.MinValue Then
                        System.Console.WriteLine(String.Format("Signig Date : {0}", signatureInfo.SigningTime.ToString("f")))
                    End If
    
                    ' get PKCS signature
                    Dim [error] As Boolean = False
                    Dim signature As Vintasoft.Imaging.Pdf.Tree.DigitalSignatures.PdfPkcsSignature = Nothing
                    Try
                        signature = signatureInfo.GetSignature()
                    Catch e As System.Exception
                        [error] = True
                        System.Console.WriteLine("PKCS signature parsing error: {0}", e.Message)
                    End Try
                    If [error] Then
                        Continue For
                    End If
    
                    ' print name of signature algorithm
                    System.Console.WriteLine(String.Format("Algorithm   : {0}", signature.SignatureAlgorithmName))
    
                    ' print information about signature certificate chain
                    System.Console.WriteLine("Sign certificate chain:")
                    Dim signCertChain As System.Security.Cryptography.X509Certificates.X509Certificate2() = signature.SigningCertificateChain
                    Dim padding As String = ""
                    For Each cert As System.Security.Cryptography.X509Certificates.X509Certificate2 In signCertChain
                        padding += "    "
                        System.Console.WriteLine("{0}Serial number: {1}", padding, cert.SerialNumber)
                        System.Console.WriteLine("{0}Issuer       : {1}", padding, cert.GetNameInfo(System.Security.Cryptography.X509Certificates.X509NameType.SimpleName, True))
                        System.Console.WriteLine("{0}Subject      : {1}", padding, cert.GetNameInfo(System.Security.Cryptography.X509Certificates.X509NameType.SimpleName, False))
                    Next
    
    
                    ' verify digital signature
                    VerifyDigitalSignature(signatureInfo, signature)
                End If
                System.Console.WriteLine()
            Next
        End Using
    End Sub
    
    ''' <summary>
    ''' Verifies the digital signature.
    ''' </summary>
    ''' <param name="signature">The signature.</param>
    ''' <param name="signatureInfo">The signature information.</param>
    ''' <returns><b>true</b> if signature is valid; otherwise, <b>false</b>.</returns>
    Public Shared Function VerifyDigitalSignature(signatureInfo As Vintasoft.Imaging.Pdf.Tree.DigitalSignatures.PdfSignatureInformation, signature As Vintasoft.Imaging.Pdf.Tree.DigitalSignatures.PdfPkcsSignature) As Boolean
        System.Console.WriteLine("Verifying signature...")
    
        Dim signatureVerifyResult As Boolean = False
        Dim embeddedTimestampVerifyResult As Boolean = False
        Dim certificateVerifyResult As Boolean = False
        Dim embeddedTimestampCertificateVerifyResult As Boolean = False
        Dim signatureCoversWholeDocument As Boolean = False
        Dim certificateChain As System.Security.Cryptography.X509Certificates.X509Chain = Nothing
        Dim timestampCertificateChain As System.Security.Cryptography.X509Certificates.X509Chain = Nothing
    
    
        ' verify signature
    
        Try
            ' check that signature covers the whole document
            signatureCoversWholeDocument = signatureInfo.SignatureCoversWholeDocument()
    
            ' verify PKCS signature
            signatureVerifyResult = signature.VerifySignature()
    
            ' if signature has embedded timestamp
            If signature.HasEmbeddedTimeStamp Then
                ' verify embedded timestamp
                embeddedTimestampVerifyResult = signature.VerifyTimestamp()
            End If
    
            ' build and verify certificate chain
            certificateChain = New System.Security.Cryptography.X509Certificates.X509Chain()
            certificateVerifyResult = certificateChain.Build(signature.SigningCertificate)
    
            ' if signature has embedded timestamp
            If signature.HasEmbeddedTimeStamp Then
                ' build and verify timestamp certificate chain
                timestampCertificateChain = New System.Security.Cryptography.X509Certificates.X509Chain()
                embeddedTimestampCertificateVerifyResult = certificateChain.Build(signature.TimestampCertificate)
    
            End If
        Catch verificationException As System.Exception
            System.Console.WriteLine("Verification failed: {0}", verificationException.Message)
            Return False
        End Try
    
        Dim pageContentModified As Boolean = False
        Dim subsequentChangesMessage As String = ""
        ' if PKCS signature verification is passed AND signature does not cover the whole document
        If signatureVerifyResult AndAlso Not signatureCoversWholeDocument Then
            Try
                ' if signature has revision info
                If signatureInfo.SignedRevision IsNot Nothing Then
                    ' check subsequent changes
                    Using documentChanges As Vintasoft.Imaging.Pdf.PdfDocumentRevisionComparer = signatureInfo.GetDocumentChanges()
                        ' check subsequent changes in pages content
                        pageContentModified = documentChanges.HasModifiedPages
    
                        ' build subsequent changes message
                        If documentChanges.ChangedPageContents.Count > 0 Then
                            subsequentChangesMessage += String.Format("{0} page(s) modified; ", documentChanges.ChangedPageContents.Count)
                        End If
                        If documentChanges.AddedPages.Count > 0 Then
                            subsequentChangesMessage += String.Format("{0} page(s) added; ", documentChanges.AddedPages.Count)
                        End If
                        If documentChanges.RemovedPages.Count > 0 Then
                            subsequentChangesMessage += String.Format("{0} page(s) removed; ", documentChanges.RemovedPages.Count)
                        End If
                        If documentChanges.RemovedAnnotations.Count > 0 Then
                            subsequentChangesMessage += String.Format("annotations(s) on {0} page(s) removed; ", documentChanges.RemovedAnnotations.Count)
                        End If
                        If documentChanges.RemovedAnnotations.Count > 0 Then
                            subsequentChangesMessage += String.Format("removed annotation(s) on {0} page(s); ", documentChanges.RemovedAnnotations.Count)
                        End If
                        If documentChanges.AddedAnnotations.Count > 0 Then
                            subsequentChangesMessage += String.Format("added annotation(s) on {0} page(s); ", documentChanges.AddedAnnotations.Count)
                        End If
                        If documentChanges.ChangedAnnotations.Count > 0 Then
                            subsequentChangesMessage += String.Format("changed annotation(s) on {0} page(s); ", documentChanges.ChangedAnnotations.Count)
                        End If
                        If documentChanges.MiscellaneousChanges.Count > 0 Then
                            subsequentChangesMessage += String.Format("miscellaneous changes: {0}; ", documentChanges.MiscellaneousChanges.Count)
                        End If
                    End Using
                End If
            Catch verificationException As System.Exception
                System.Console.WriteLine("Verification failed: {0}", verificationException.Message)
                Return False
            End Try
        End If
    
        ' print signature verification result
    
        ' if PKCS signature verification is failed OR
        ' signature does not cover the whole document AND page(s) content is modified
        If Not signatureVerifyResult OrElse (Not signatureCoversWholeDocument AndAlso pageContentModified) Then
            System.Console.WriteLine("Signature is INVALID.")
        ' if certificate verification is failed
        ElseIf Not certificateVerifyResult OrElse (signature.HasEmbeddedTimeStamp AndAlso (Not embeddedTimestampCertificateVerifyResult OrElse Not embeddedTimestampVerifyResult)) Then
            System.Console.WriteLine("Signature validity is UNKNOWN.")
        Else
            System.Console.WriteLine("Signature is VALID.")
        End If
    
    
        ' print signature verification details
    
        ' if signature verification is successful
        If signatureVerifyResult Then
            ' if signature covers the whole document
            If signatureCoversWholeDocument Then
                System.Console.WriteLine("    Signature verification: Document has not been modified since this signature was applied.")
            Else
                ' if signature does NOT cover the whole document
                If pageContentModified Then
                    System.Console.WriteLine("    Signature verification: Document has been modified or corrupted since it was signed.")
                    System.Console.WriteLine(String.Format("    Subsequent changes: {0}.", subsequentChangesMessage))
                ElseIf subsequentChangesMessage <> "" Then
                    System.Console.WriteLine("    Signature verification: The revision of the document that was covered by this signature has not been altered; however, there have been subsequent changes to the document.")
                    System.Console.WriteLine(String.Format("    Subsequent changes: {0}.", subsequentChangesMessage))
                Else
                    System.Console.WriteLine("    Signature verification: Document has not been modified since this signature was applied.")
                End If
            End If
        Else
            ' if signature verification is NOT successful
            System.Console.WriteLine("    Signature verification: Document has been modified or corrupted since it was signed.")
        End If
    
        ' if signature has embedded timestamp
        If signature.HasEmbeddedTimeStamp Then
            If embeddedTimestampVerifyResult Then
                System.Console.WriteLine("    Timestamp verification: Timestamp is valid.")
            Else
                System.Console.WriteLine("    Timestamp verification: Timestamp is valid.")
            End If
        End If
    
    
        ' print certificate verification details
    
        ' if certificate chain is present
        If certificateChain IsNot Nothing Then
            ' if certificate verification is successful
            If certificateVerifyResult Then
                System.Console.WriteLine("    Certificate verification: Signer's certificate is valid.")
            Else
                ' if certificate verification is NOT successful
                ' print certificate verification status
                System.Console.WriteLine("    Certificate verification: Signer's certificate is invalid:")
                For Each status As System.Security.Cryptography.X509Certificates.X509ChainStatus In certificateChain.ChainStatus
                    System.Console.Write(String.Format("        {0}: {1}", status.Status, status.StatusInformation))
                Next
            End If
        End If
    
        ' if timestamp certificate chain is present
        If timestampCertificateChain IsNot Nothing Then
            ' if timestamp certificate verification is successful
            If embeddedTimestampCertificateVerifyResult Then
                System.Console.WriteLine("    Timestamp certificate verification: Signer's certificate is valid.")
            Else
                ' if timestamp certificate verification is NOT successful
                ' print certificate verification status
                System.Console.WriteLine("    Timestamp certificate verification: Signer's certificate is invalid:")
                For Each status As System.Security.Cryptography.X509Certificates.X509ChainStatus In timestampCertificateChain.ChainStatus
                    System.Console.Write(String.Format("        {0}: {1}", status.Status, status.StatusInformation))
                Next
            End If
        End If
    
        ' if signature is not verified
        If Not signatureVerifyResult Then
            Return False
        End If
    
        ' if signature does NOT cover the whole document and page content was modified
        If Not signatureCoversWholeDocument AndAlso pageContentModified Then
            Return False
        End If
    
        ' if signature certificate is NOT verified
        If Not certificateVerifyResult Then
            Return False
        End If
    
        If signature.HasEmbeddedTimeStamp Then
            ' if timestamp is NOT verified
            If Not embeddedTimestampVerifyResult Then
                Return False
            End If
    
            ' if timestamp certifiacet is NOT verified
            If Not embeddedTimestampCertificateVerifyResult Then
                Return False
            End If
        End If
    
        ' sigature is VALID
        Return True
    End Function
    


    IMPORTANT! Certificate verification will be performed successfully only if certificate is added to the list of trusted root certificates of current Windows user. You can read more on how to manage trusted root certificates here: https://technet.microsoft.com/en-us/library/cc754841.aspx.


    Remove digital signature from PDF document

    To remove the signature from PDF document is necessary to do the following:

    Here is an example, that demonstrates how to remove a signature from PDF document:
    /// <summary>
    /// Removes all digital signatures from PDF document.
    /// </summary>
    /// <param name="pdfFilename">The filename of PDF document.</param>
    public static void RemoveDigitalSignaturesFromPdfDocument(string pdfFilename)
    {
        // open PDF document
        using (Vintasoft.Imaging.Pdf.PdfDocument document =
            new Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename))
        {
            // if PDF document has PDF interactive form
            if (document.InteractiveForm != null)
            {
                // get reference to the interactive form of PDF document
                Vintasoft.Imaging.Pdf.Tree.InteractiveForms.PdfDocumentInteractiveForm form =
                    document.InteractiveForm;
    
                // get all signature fields of PDF document
                Vintasoft.Imaging.Pdf.Tree.InteractiveForms.PdfInteractiveFormSignatureField[] signatureFields =
                    form.GetSignatureFields();
    
                // for each signature fields
                foreach (Vintasoft.Imaging.Pdf.Tree.InteractiveForms.PdfInteractiveFormField field in signatureFields)
                {
                    // remove signature field
                    field.Remove();
                }
    
                // pack PDF document
                document.Pack();
            }
        }
    }
    
    ''' <summary>
    ''' Removes all digital signatures from PDF document.
    ''' </summary>
    ''' <param name="pdfFilename">The filename of PDF document.</param>
    Public Shared Sub RemoveDigitalSignaturesFromPdfDocument(pdfFilename As String)
        ' open PDF document
        Using document As New Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename)
            ' if PDF document has PDF interactive form
            If document.InteractiveForm IsNot Nothing Then
                ' get reference to the interactive form of PDF document
                Dim form As Vintasoft.Imaging.Pdf.Tree.InteractiveForms.PdfDocumentInteractiveForm = document.InteractiveForm
    
                ' get all signature fields of PDF document
                Dim signatureFields As Vintasoft.Imaging.Pdf.Tree.InteractiveForms.PdfInteractiveFormSignatureField() = form.GetSignatureFields()
    
                ' for each signature fields
                For Each field As Vintasoft.Imaging.Pdf.Tree.InteractiveForms.PdfInteractiveFormField In signatureFields
                    ' remove signature field
                    field.Remove()
                Next
    
                ' pack PDF document
                document.Pack()
            End If
        End Using
    End Sub