Digital signature is used for authenticating the identity of a user and the validity of the document contents.
The SDK allows to:
' The project, which uses this code, must have references to the following assemblies: ' - Vintasoft.Imaging ' - Vintasoft.Imaging.Pdf ''' <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
// The project, which uses this code, must have references to the following assemblies: // - Vintasoft.Imaging // - Vintasoft.Imaging.Pdf /// <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); }
' The project, which uses this code, must have references to the following assemblies: ' - Vintasoft.Imaging ' - Vintasoft.Imaging.Pdf ''' <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
// The project, which uses this code, must have references to the following assemblies: // - Vintasoft.Imaging // - Vintasoft.Imaging.Pdf /// <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; }
' The project, which uses this code, must have references to the following assemblies: ' - Vintasoft.Imaging ' - Vintasoft.Imaging.Pdf ''' <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
// The project, which uses this code, must have references to the following assemblies: // - Vintasoft.Imaging // - Vintasoft.Imaging.Pdf /// <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(); } } }