VintaSoft Imaging .NET SDK 15.0: Documentation for .NET developer
In This Topic
    PDF: How to add digital signature to PDF document
    In This Topic
    PDF document can be signed using the digital certificate, which can be obtained from a trusted Certificate Authority (CA) such as DigiCert or GlobalSign. Also it is possible to create self-signed digital certificate for internal or testing purposes.

    VintaSoft Imaging .NET SDK can sign PDF document using digital certificate. SDK uses "byte range" technology to a sign a PDF document, i.e. SDK calculates the checksum for binary data of the entire document. Calculated checksum and digital signature is stored in the signature field of the interactive form of PDF document.

    If PDF document should be signed using digital signature, the following steps must be done:
    If PDF document should contain signature field for further document signing by other person, the following steps must be done:
    Here is C#/VB.NET code that demonstrates how to sign and timestamp a PDF document:
    /// <summary>
    /// Signs a PDF or PDF/A document using specified PFX file.
    /// </summary>
    /// <param name="inputFilename">The filename of input PDF document.</param>
    /// <param name="outputFilename">The filename of output PDF document.</param>
    /// <param name="pfxFileName">The name of PFX file.</param>
    /// <param name="pfxFilePassword">The password for PDF file.</param>
    public static void SignDocument(
        string inputFilename,
        string outputFilename,
        string pfxFileName,
        string pfxFilePassword)
    {
        Vintasoft.Imaging.Pdf.PdfDocumentConformance conformance =
            Vintasoft.Imaging.Pdf.PdfDocumentConformance.Undefined;
        System.Security.Cryptography.X509Certificates.X509Certificate2 certificate =
            new System.Security.Cryptography.X509Certificates.X509Certificate2(pfxFileName, pfxFilePassword);
    
        SignDocument(inputFilename, outputFilename, conformance, certificate, false, null);
    }
    
    /// <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 and timestamps a PDF or PDF/A document.
    /// </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 the 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="signatureFieldNumber">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 signatureFieldNumber)
    {
        // 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 * signatureFieldNumber;
    
        // 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}", signatureFieldNumber), 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 PDF file.
    ''' </summary>
    ''' <param name="inputFilename">The filename of input PDF document.</param>
    ''' <param name="outputFilename">The filename of output PDF document.</param>
    ''' <param name="pfxFileName">The name of PFX file.</param>
    ''' <param name="pfxFilePassword">The password for PDF file.</param>
    Public Shared Sub SignDocument(inputFilename As String, outputFilename As String, _
        pfxFileName As String, pfxFilePassword As String)
    
        Dim conformance As Vintasoft.Imaging.Pdf.PdfDocumentConformance = Vintasoft.Imaging.Pdf.PdfDocumentConformance.Undefined
        Dim certificate As System.Security.Cryptography.X509Certificates.X509Certificate2 = _
            new System.Security.Cryptography.X509Certificates.X509Certificate2(pfxFileName, pfxFilePassword)
    
        SignDocument(inputFilename, outputFilename, conformance, certificate, False, Nothing)
    End Sub
    
    ''' <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 and timestamps a PDF or PDF/A document.
    ''' </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 the 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="signatureFieldNumber">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, signatureFieldNumber 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 * signatureFieldNumber
    
        ' 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}", signatureFieldNumber), 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
    


    Please read how to verify the digital signatures in PDF document here.
    Please read how to remove digital signature from PDF document here.