< Windows samples

DigitalSignaturesTest - VB

Demonstrates the basic usage of high-level digital signature API to digitally sign and/or certify PDF documents.

'
' Copyright (c) 2001-2018 by PDFTron Systems Inc. All Rights Reserved.
'

''----------------------------------------------------------------------------------------------------------------------
'' This sample demonstrates the basic usage of high-level digital signature API in PDFNet.
''
'' The following steps are typically used to add a digital signature to a PDF:
''
''     1. Extend and implement a new SignatureHandler. The SignatureHandler will be used to add or validate/check a
''        digital signature.
''     2. Create an instance of the implemented SignatureHandler and register it with PDFDoc with
''        pdfdoc.AddSignatureHandler(). The method returns an ID that can be used later to associate a SignatureHandler
''        with a field.
''     3. Find the required 'e_signature' field in the existing document or create a new field.
''     4. Call field.UseSignatureHandler() with the ID of your handler.
''     5. Call pdfdoc.Save()
''
'' Additional processing can be done before document is signed. For example, UseSignatureHandler() returns an instance
'' of SDF dictionary which represents the signature dictionary (or the /V entry of the form field). This can be used to
'' add additional information to the signature dictionary (e.g. Name, Reason, Location, etc.).
''
'' Although the steps above describes extending the SignatureHandler class, this sample demonstrates the use of
'' StdSignatureHandler (a built-in SignatureHandler in PDFNet) to sign a PDF file.
''----------------------------------------------------------------------------------------------------------------------

'' In order to use .NET Framework's Cryptography library, define "USE_DOTNET_CRYPO" and then add System.Security to
'' references list.

Imports System
Imports System.Collections.Generic
Imports System.IO
#If USE_DOTNET_CRYPTO Then
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Pkcs
Imports System.Security.Cryptography.X509Certificates
#End If ' USE_DOTNET_CRYPTO

Imports pdftron
Imports pdftron.Common
Imports pdftron.PDF
Imports pdftron.PDF.Annots
Imports pdftron.SDF

#If USE_DOTNET_CRYPTO Then
Class DotNetCryptoSignatureHandler
    Inherits SignatureHandler
    Private m_data As List(Of Byte)
    Private m_signingCert As String
    Private m_certPassword As String

    Public Sub New(ByVal signingCert As String, ByVal password As String)
        m_signingCert = signingCert
        m_certPassword = password
        m_data = New List(Of Byte)()
    End Sub

    Public Overrides Sub AppendData(ByVal data As Byte())
        m_data.AddRange(data)
    End Sub

    Public Overrides Function Reset() As Boolean
        m_data.Clear()
        Return (True)
    End Function

    Public Overrides Function CreateSignature() As Byte()
        Try
            Dim ci As New ContentInfo(m_data.ToArray())
            Dim sc As New SignedCms(ci, True)
            Dim cert As New X509Certificate2(m_signingCert, m_certPassword)
            Dim cs As New CmsSigner()
            cs.Certificate = cert
            sc.ComputeSignature(cs)
            Dim sig As Byte() = sc.Encode()
            Return (sig)
        Catch e As Exception
            Console.[Error].WriteLine(e)
        End Try
        Return (Nothing)
    End Function

    Public Overrides Function GetName() As String
        Return ("Adobe.PPKLite")
    End Function

    Protected Overrides Sub Finalize()
        Try
            Console.Out.WriteLine("DotNetCryptoSignatureHandler Destructor.")
        Finally
            MyBase.Finalize()
        End Try
    End Sub
End Class
#End If ' USE_DOTNET_CRYPTO

Module Module1

    ''' <summary>
    ''' This functions add an approval signature to the PDF document. The original PDF document contains a blank form field
    ''' that is prepared for a user to sign. The following code demonstrate how to sign this document using PDFNet.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function SignPDF() As Boolean
        Dim result As Boolean = True
        Dim infile As String = "../../../../TestFiles/doc_to_sign.pdf"
        Dim outfile As String = "../../../../TestFiles/Output/signed_doc.pdf"
        Dim certfile As String = "../../../../TestFiles/pdftron.pfx"
        Dim imagefile As String = "../../../../TestFiles/signature.jpg"

        Console.Out.WriteLine("Signing PDF document: \""{0}\"".", infile)

        Using doc As New PDFDoc(infile)
            Try
#If USE_DOTNET_CRYPTO Then
                ' Create a new instance of the SignatureHandler.
                Dim sigHandler As DotNetCryptoSignatureHandler = New DotNetCryptoSignatureHandler(certfile, "password")
                ' Add the SignatureHandler instance to PDFDoc, making sure to keep track of it using the ID returned.
                Dim sigHandlerId As SignatureHandlerId = doc.AddSignatureHandler(sigHandler)
#Else
                Dim sigHandlerId As SignatureHandlerId = doc.AddStdSignatureHandler(certfile, "password")
#End If ' USE_DOTNET_CRYPTO

                ' Obtain the signature form field from the PDFDoc via Annotation;
                Dim sigField As Field = doc.GetField("Signature1")
                Dim widgetAnnot As Widget = New Widget(sigField.GetSDFObj)

                ' Tell PDFNet to use the SignatureHandler created to sign the new signature form field.
                Dim sigDict As Obj = sigField.UseSignatureHandler(sigHandlerId)

                ' Add more information to the signature dictionary
                sigDict.PutName("SubFilter", "adbe.pkcs7.detached")
                sigDict.PutString("Name", "PDFTron")
                sigDict.PutString("Location", "Vancouver, BC")
                sigDict.PutString("Reason", "Document verification.")

                ' Add the signature appearance
                Dim apWriter As ElementWriter = New ElementWriter
                Dim apBuilder As ElementBuilder = New ElementBuilder
                apWriter.Begin(doc)
                Dim sigImg As Image = Image.Create(doc, imagefile)
                Dim w As Double = sigImg.GetImageWidth
                Dim h As Double = sigImg.GetImageHeight
                Dim apElement As Element = apBuilder.CreateImage(sigImg, 0, 0, w, h)
                apWriter.WritePlacedElement(apElement)
                Dim apObj As Obj = apWriter.End
                apObj.PutRect("BBox", 0, 0, w, h)
                apObj.PutName("Subtype", "Form")
                apObj.PutName("Type", "XObject")
                apWriter.Begin(doc)
                apElement = apBuilder.CreateForm(apObj)
                apWriter.WritePlacedElement(apElement)
                apObj = apWriter.End
                apObj.PutRect("BBox", 0, 0, w, h)
                apObj.PutName("Subtype", "Form")
                apObj.PutName("Type", "XObject")

                widgetAnnot.SetAppearance(apObj)
                widgetAnnot.RefreshAppearance()

                ' Save the PDFDoc. Once the method below is called, PDFNet will also sign the document using the information
                ' provided.
                doc.Save(outfile, 0)

                Console.Out.WriteLine("Finished signing PDF document.")
            Catch ex As Exception
                Console.Error.WriteLine(ex)
                result = False
            End Try
        End Using

        Return result
    End Function

    Function CertifyPDF() As Boolean
        Dim result As Boolean = True
        Dim infile As String = "../../../../TestFiles/newsletter.pdf"
        Dim outfile As String = "../../../../TestFiles/Output/newsletter_certified.pdf"
        Dim certfile As String = "../../../../TestFiles/pdftron.pfx"

        Console.Out.WriteLine("Certifying PDF document: \""{0}\"".", infile)

        ' Open an existing PDF
        Using doc As New PDFDoc(infile)
            Try
#If USE_DOTNET_CRYPTO Then
                ' Create a new instance of the SignatureHandler.
                Dim sigHandler As DotNetCryptoSignatureHandler = New DotNetCryptoSignatureHandler(certfile, "password")
                ' Add the SignatureHandler instance to PDFDoc, making sure to keep track of it using the ID returned.
                Dim sigHandlerId As SignatureHandlerId = doc.AddSignatureHandler(sigHandler)
#Else
                Dim sigHandlerId As SignatureHandlerId = doc.AddStdSignatureHandler(certfile, "password")
#End If ' USE_DOTNET_CRYPTO

                ' Create new signature form field in the PDFDoc.
                Dim sigField As Field = doc.FieldCreate("Signature1", Field.Type.e_signature)

                Dim page1 As Page = doc.GetPage(1)
                Dim widgetAnnot As Widget = Widget.Create(doc.GetSDFDoc, New Rect(0, 0, 0, 0), sigField)
                page1.AnnotPushBack(widgetAnnot)
                widgetAnnot.SetPage(page1)
                Dim widgetObj As Obj = widgetAnnot.GetSDFObj
                widgetObj.PutNumber("F", 132)
                widgetObj.PutName("Type", "Annot")

                ' Tell PDFNet to use the SignatureHandler created to sign the new signature form field
                Dim sigDict As Obj = sigField.UseSignatureHandler(sigHandlerId)

                ' Add more information to the signature dictionary
                sigDict.PutName("SubFilter", "adbe.pkcs7.detached")
                sigDict.PutString("Name", "PDFTron")
                sigDict.PutString("Location", "Vancouver, BC")
                sigDict.PutString("Reason", "Document verification.")
                Dim root As Obj = doc.GetRoot
                Dim perms As Obj = root.PutDict("Perms")

                ' add the sigDict as DocMDP (indirect) in Perms
                perms.Put("DocMDP", sigDict)

                ' add the additional DocMDP transform params
                Dim refObj As Obj = sigDict.PutArray("Reference")
                Dim transform As Obj = refObj.PushBackDict
                transform.PutName("TransformMethod", "DocMDP")
                transform.PutName("Type", "SigRef")
                Dim transformParams As Obj = transform.PutDict("TransformParams")
                transformParams.PutNumber("P", 1) ' Set permissions as necessary.
                transformParams.PutName("Type", "TransformParams")
                transformParams.PutName("V", "1.2")

                ' Save the PDFDoc. Once the method below is called, PDFNet will also sign the document using the information
                ' provided.
                doc.Save(outfile, 0)

                Console.Out.WriteLine("Finished certifying PDF document.")
            Catch ex As Exception
                Console.Error.WriteLine(ex)
                result = False
            End Try
        End Using

        Return result
    End Function

    Dim pdfNetLoader As PDFNetLoader = pdftron.PDFNetLoader.Instance()

    Sub Main()
        ' Initialize PDFNet
        PDFNet.Initialize()
        Dim result As Boolean = True
        If Not SignPDF Then
            result = False
        End If
        If Not CertifyPDF Then
            result = False
        End If
        Console.Out.WriteLine()
        If Not result Then
            Console.Out.WriteLine("Tests failed.")
            Return
        End If
        Console.Out.WriteLine("All tests passed.")
    End Sub

End Module