Some test text!

menu
search

Digitally sign PDF files in VB

Sample VB code to use PDFTron SDK's high-level digital signature API for digitally signing and/or certifying PDF files. Learn more about our PDF Digital Signature Library.

Get StartedSamplesDownload

To run this sample, get started with a free trial of PDFTron SDK.

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

''----------------------------------------------------------------------------------------------------------------------
'' This sample demonstrates the basic usage of high-level digital signature API in PDFNet.
''
'' The following steps reflect typical intended usage of the digital signature API:
''
''	0.	Start with a PDF with or without form fields in it that one would like to lock (or, one can add a field, see (1)).
''	
''	1.	EITHER: 
''		(a) Call doc.CreateDigitalSignatureField, optionally providing a name. You receive a DigitalSignatureField.
''		-OR-
''		(b) If you didn't just create the digital signature field that you want to sign/certify, find the existing one within the 
''		document by using PDFDoc.DigitalSignatureFieldIterator or by using PDFDoc.GetField to get it by its fully qualified name.
''	
''	2.	Create a signature widget annotation, and pass the DigitalSignatureField that you just created or found. 
''		If you want it to be visible, provide a Rect argument with a non-zero width or height, and don't set the
''		NoView and Hidden flags. [Optionally, add an appearance to the annotation when you wish to sign/certify.]
''		
''	[3. (OPTIONAL) Add digital signature restrictions to the document using the field modification permissions (SetFieldPermissions) 
''		or document modification permissions functions (SetDocumentPermissions) of DigitalSignatureField. These features disallow 
''		certain types of changes to be made to the document without invalidating the cryptographic digital signature's hash once it
''		is signed.]
''		
''	4. 	Call either CertifyOnNextSave or SignOnNextSave. There are three overloads for each one (six total):
''		a.	Taking a PKCS #12 keyfile path and its password
''		b.	Taking a buffer containing a PKCS #12 private keyfile and its password
''		c.	Taking a unique identifier of a signature handler registered with the PDFDoc. This overload is to be used
''			in the following fashion: 
''			i)		Extend and implement a new SignatureHandler. The SignatureHandler will be used to add or 
''					validate/check a digital signature.
''			ii)		Create an instance of the implemented SignatureHandler and register it with PDFDoc with 
''					pdfdoc.AddSignatureHandler(). The method returns a SignatureHandlerId.
''			iii)	Call SignOnNextSaveWithCustomHandler/CertifyOnNextSaveWithCustomHandler with the SignatureHandlerId.
''		NOTE: It is only possible to sign/certify one signature per call to the Save function.
''	
''	5.	Call pdfdoc.Save(). This will also create the digital signature dictionary and write a cryptographic hash to it.
''		IMPORTANT: If there are already signed/certified digital signature(s) in the document, you must save incrementally
''		so as to not invalidate the other signature's('s) cryptographic hashes. 
''
'' 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_CRYPTO" 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

'''''''''''''''''''' Here follows an example of how to implement a custom signature handler. ''''''''''
#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
'''''''''' End of the DotNetCryptoSignatureHandler custom handler code. ''''''''''''''''''''

Module Module1
	Dim input_path As String = "../../../../TestFiles/"
	Dim output_path As String = "../../../../TestFiles/Output/"

	Sub CertifyPDF(ByVal in_docpath As String, ByVal in_cert_field_name As String, ByVal in_private_key_file_path As String, ByVal in_keyfile_password As String, ByVal in_appearance_image_path As String, ByVal in_outpath As String)
		Console.Out.WriteLine("================================================================================")
		Console.Out.WriteLine("Certifying PDF document")

		' Open an existing PDF
		Using doc As PDFDoc = New PDFDoc(in_docpath)
			Console.Out.WriteLine("PDFDoc has " & (If(doc.HasSignatures(), "signatures", "no signatures")))
			
			Dim page1 As Page = doc.GetPage(1)
			
			' Create a random text field that we can lock using the field permissions feature.
			Dim annot1 As TextWidget = TextWidget.Create(doc, New Rect(50, 550, 350, 600), "asdf_test_field")
			page1.AnnotPushBack(annot1)
			
			' Create new signature form field in the PDFDoc. The name argument is optional;
			' leaving it empty causes it to be auto-generated. However, you may need the name for later.
			' Acrobat doesn't show digsigfield in side panel if it's without a widget. Using a
			' Rect with 0 width and 0 height, or setting the NoPrint/Invisible flags makes it invisible.
			Dim certification_sig_field As DigitalSignatureField = doc.CreateDigitalSignatureField(in_cert_field_name)
			Dim widgetAnnot As SignatureWidget = SignatureWidget.Create(doc, New Rect(0, 100, 200, 150), certification_sig_field)
			page1.AnnotPushBack(widgetAnnot)
			
			' (OPTIONAL) Add an appearance.
			
			' Widget AP from image
			Dim img As Image = Image.Create(doc, in_appearance_image_path)
			widgetAnnot.CreateSignatureAppearance(img)
			' End of optional appearance-adding code.
			
			' Add permissions. Lock the random text field.
			Console.Out.WriteLine("Adding document permissions.")
			certification_sig_field.SetDocumentPermissions(DigitalSignatureField.DocumentPermissions.e_annotating_formfilling_signing_allowed)
			Console.Out.WriteLine("Adding field permissions.")
			Dim fields_to_lock As String() = New String(0) {}
			fields_to_lock(0) = "asdf_test_field"
			certification_sig_field.SetFieldPermissions(DigitalSignatureField.FieldPermissions.e_include, fields_to_lock)

#If USE_DOTNET_CRYPTO Then
			Dim sigHandler As DotNetCryptoSignatureHandler = New DotNetCryptoSignatureHandler(in_private_key_file_path, in_keyfile_password)
			Dim sigHandlerId As SignatureHandlerId = doc.AddSignatureHandler(sigHandler)
			found_approval_signature_digsig_field.CertifyOnNextSaveWithCustomHandler(sigHandlerId)
#Else
			certification_sig_field.CertifyOnNextSave(in_private_key_file_path, in_keyfile_password)
#End If ' USE_DOTNET_CRYPTO
			
			' (OPTIONAL) Add more information to the signature dictionary.
			certification_sig_field.SetLocation("Vancouver, BC")
			certification_sig_field.SetReason("Document certification.")
			certification_sig_field.SetContactInfo("www.pdftron.com")
			' End of optional sig info code.
			
			' Save the PDFDoc. Once the method below is called, PDFNetC will also sign the document using the information provided.
			doc.Save(in_outpath, 0)
		End Using

		Console.Out.WriteLine("================================================================================")
	End Sub

	Sub SignPDF(ByVal in_docpath As String, ByVal in_approval_field_name As String, ByVal in_private_key_file_path As String, ByVal in_keyfile_password As String, ByVal in_appearance_img_path As String, ByVal in_outpath As String)
		Console.Out.WriteLine("================================================================================")
		Console.Out.WriteLine("Signing PDF document")

		' Open an existing PDF
		Using doc As PDFDoc = New PDFDoc(in_docpath)
			' Sign the approval signatures.
			Dim found_approval_field As Field = doc.GetField(in_approval_field_name)
			Dim found_approval_signature_digsig_field As DigitalSignatureField = New DigitalSignatureField(found_approval_field)
			Dim img2 As Image = Image.Create(doc, in_appearance_img_path)
			Dim found_approval_signature_widget As SignatureWidget = New SignatureWidget(found_approval_field.GetSDFObj())
			found_approval_signature_widget.CreateSignatureAppearance(img2)

#If USE_DOTNET_CRYPTO Then
			Dim sigHandler As DotNetCryptoSignatureHandler = New DotNetCryptoSignatureHandler(in_private_key_file_path, in_keyfile_password)
			Dim sigHandlerId As SignatureHandlerId = doc.AddSignatureHandler(sigHandler)
			found_approval_signature_digsig_field.SignOnNextSaveWithCustomHandler(sigHandlerId)
#Else
			found_approval_signature_digsig_field.SignOnNextSave(in_private_key_file_path, in_keyfile_password)
#End If ' USE_DOTNET_CRYPTO

			doc.Save(in_outpath, SDFDoc.SaveOptions.e_incremental)
		End Using

		Console.Out.WriteLine("================================================================================")
	End Sub

	Sub ClearSignature(ByVal in_docpath As String, ByVal in_digsig_field_name As String, ByVal in_outpath As String)
		Console.Out.WriteLine("================================================================================")
		Console.Out.WriteLine("Clearing certification signature")

		Using doc As PDFDoc = New PDFDoc(in_docpath)
			Dim digsig As DigitalSignatureField = New DigitalSignatureField(doc.GetField(in_digsig_field_name))
			
			Console.Out.WriteLine("Clearing signature: " & in_digsig_field_name)
			digsig.ClearSignature()

			If Not digsig.HasCryptographicSignature() Then
				Console.Out.WriteLine("Cryptographic signature cleared properly.")
			End If

			' Save incrementally so as to not invalidate other signatures' hashes from previous saves.
			doc.Save(in_outpath, SDFDoc.SaveOptions.e_incremental)
		End Using

		Console.Out.WriteLine("================================================================================")
	End Sub

	Sub PrintSignaturesInfo(ByVal in_docpath As String)
		Console.Out.WriteLine("================================================================================")
		Console.Out.WriteLine("Reading and printing digital signature information")

		Using doc As PDFDoc = New PDFDoc(in_docpath)

			If Not doc.HasSignatures() Then
				Console.Out.WriteLine("Doc has no signatures.")
				Console.Out.WriteLine("================================================================================")
				Return
			Else
				Console.Out.WriteLine("Doc has signatures.")
			End If

			Dim fitr As FieldIterator = doc.GetFieldIterator()

			While fitr.HasNext()
				If fitr.Current().IsLockedByDigitalSignature() Then
					Console.Out.WriteLine("==========" & vbLf & "Field locked by a digital signature")
				Else
					Console.Out.WriteLine("==========" & vbLf & "Field not locked by a digital signature")
				End If

				Console.Out.WriteLine("Field name: " & fitr.Current().GetName())
				Console.Out.WriteLine("==========")
				fitr.Next()
			End While

			Console.Out.WriteLine("====================" & vbLf & "Now iterating over digital signatures only." & vbLf & "====================")
			
			Dim digsig_fitr As DigitalSignatureFieldIterator = doc.GetDigitalSignatureFieldIterator()
			While digsig_fitr.HasNext()
				Console.Out.WriteLine("==========")
				Console.Out.WriteLine("Field name of digital signature: " & New Field(digsig_fitr.Current().GetSDFObj()).GetName())
				Dim digsigfield As DigitalSignatureField = digsig_fitr.Current()

				If Not digsigfield.HasCryptographicSignature() Then
					Console.Out.WriteLine("Either digital signature field lacks a digital signature dictionary, " &
					"or digital signature dictionary lacks a cryptographic hash entry. " & 
					"Digital signature field is not presently considered signed." & 
					vbLf & "==========")
					digsig_fitr.Next()
					Continue While
				End If

				Dim cert_count As Integer = digsigfield.GetCertCount()
				Console.Out.WriteLine("Cert count: " & cert_count)
				For i As Integer = 0 To cert_count - 1
					Dim cert As Byte() = digsigfield.GetCert(i)
					Console.Out.WriteLine("Cert #" & i & " size: " & cert.Length)
				Next

				Dim subfilter As DigitalSignatureField.SubFilterType = digsigfield.GetSubFilter()
				Console.Out.WriteLine("Subfilter type: " & CInt(subfilter))

				If subfilter <> DigitalSignatureField.SubFilterType.e_ETSI_RFC3161 Then
					Console.Out.WriteLine("Signature's signer: " & digsigfield.GetSignatureName())
					Dim signing_time As pdftron.PDF.Date = digsigfield.GetSigningTime()
					If signing_time.IsValid() Then
						Console.Out.WriteLine("Signing day: " & CInt(signing_time.day))
					End If
					Console.Out.WriteLine("Location: " & digsigfield.GetLocation())
					Console.Out.WriteLine("Reason: " & digsigfield.GetReason())
					Console.Out.WriteLine("Contact info: " & digsigfield.GetContactInfo())
				Else
					Console.Out.WriteLine("SubFilter == e_ETSI_RFC3161 (DocTimeStamp; no signing info)" & vbLf)
				End If

				Console.Out.WriteLine((If((digsigfield.HasVisibleAppearance()), "Visible", "Not visible")))
				
				Dim digsig_doc_perms As DigitalSignatureField.DocumentPermissions = digsigfield.GetDocumentPermissions()
				Dim locked_fields As String() = digsigfield.GetLockedFields()
				For Each field_name As String In locked_fields
					Console.Out.WriteLine("This digital signature locks a field named: " & field_name)
				Next

				Select Case digsig_doc_perms
					Case DigitalSignatureField.DocumentPermissions.e_no_changes_allowed
						Console.Out.WriteLine("No changes to the document can be made without invalidating this digital signature.")
					Case DigitalSignatureField.DocumentPermissions.e_formfilling_signing_allowed
						Console.Out.WriteLine("Page template instantiation, form filling, and signing digital signatures are allowed without invalidating this digital signature.")
					Case DigitalSignatureField.DocumentPermissions.e_annotating_formfilling_signing_allowed
						Console.Out.WriteLine("Annotating, page template instantiation, form filling, and signing digital signatures are allowed without invalidating this digital signature.")
					Case DigitalSignatureField.DocumentPermissions.e_unrestricted
						Console.Out.WriteLine("Document not restricted by this digital signature.")
					Case Else
						Throw New Exception("Unrecognized digital signature document permission level.")
				End Select

				Console.Out.WriteLine("==========")
				digsig_fitr.Next()
			End While
		End Using

		Console.Out.WriteLine("================================================================================")
	End Sub

	Dim pdfNetLoader As PDFNetLoader
    Sub New()
        pdfNetLoader = pdftron.PDFNetLoader.Instance()
    End Sub

	Sub Main()
		' Initialize PDFNet
		PDFNet.Initialize()
		
		Dim result As Boolean = True

		'''''''''''''''''''' TEST 0: 
		' Create an approval signature field that we can sign after certifying.
		' (Must be done before calling CertifyOnNextSave/SignOnNextSave/WithCustomHandler.)
		Try
			Using doc As PDFDoc = New PDFDoc(input_path & "tiger.pdf")
				Dim approval_signature_field As DigitalSignatureField = doc.CreateDigitalSignatureField("PDFTronApprovalSig")
				Dim widgetAnnotApproval As SignatureWidget = SignatureWidget.Create(doc, New Rect(300, 300, 500, 200), approval_signature_field)
				Dim page1 As Page = doc.GetPage(1)
				page1.AnnotPushBack(widgetAnnotApproval)
				doc.Save(output_path & "tiger_withApprovalField_output.pdf", SDFDoc.SaveOptions.e_remove_unused)
			End Using
		Catch e As Exception
			Console.[Error].WriteLine(e)
			result = False
		End Try

		'''''''''''''''''''' TEST 1: certify a PDF.
		Try
			CertifyPDF(input_path & "tiger_withApprovalField.pdf", "PDFTronCertificationSig", input_path & "pdftron.pfx", "password", input_path & "pdftron.bmp", output_path & "tiger_withApprovalField_certified_output.pdf")
			PrintSignaturesInfo(output_path & "tiger_withApprovalField_certified_output.pdf")
		Catch e As Exception
			Console.[Error].WriteLine(e)
			result = False
		End Try

		'''''''''''''''''''' TEST 2: sign a PDF with a certification and an unsigned signature field in it.
		Try
			SignPDF(input_path & "tiger_withApprovalField_certified.pdf", "PDFTronApprovalSig", input_path & "pdftron.pfx", "password", input_path & "signature.jpg", output_path & "tiger_withApprovalField_certified_approved_output.pdf")
			PrintSignaturesInfo(output_path & "tiger_withApprovalField_certified_approved_output.pdf")
		Catch e As Exception
			Console.[Error].WriteLine(e)
			result = False
		End Try

		'''''''''''''''''''' TEST 3: Clear a certification from a document that is certified and has two approval signatures.
		Try
			ClearSignature(input_path & "tiger_withApprovalField_certified_approved.pdf", "PDFTronCertificationSig", output_path & "tiger_withApprovalField_certified_approved_certcleared_output.pdf")
			PrintSignaturesInfo(output_path & "tiger_withApprovalField_certified_approved_certcleared_output.pdf")
		Catch e As Exception
			Console.[Error].WriteLine(e)
			result = False
		End Try

		'''''''''''''''''''' End of tests. ''''''''''''''''''''
		
		If result Then
			Console.Out.WriteLine("Tests successful." & vbLf & "==========")
		Else
			Console.Out.WriteLine("Tests FAILED!!!" & vbLf & "==========")
		End If
	End Sub
End Module
close

Free Trial

Get unlimited trial usage of PDFTron SDK to bring accurate, reliable, and fast document processing capabilities to any application or workflow.

Select a platform to get started with your free trial.

Unlimited usage. No email address required.

PDFTron Receives USD$71 Million Growth Investment Led By Silversmith Capital Partners

Learn More
close