
'Declaration Public Class PdfSignatureInformation Inherits Vintasoft.Imaging.Pdf.Tree.PdfTreeNodeBase
public class PdfSignatureInformation : Vintasoft.Imaging.Pdf.Tree.PdfTreeNodeBase
public __gc class PdfSignatureInformation : public Vintasoft.Imaging.Pdf.Tree.PdfTreeNodeBase*
public ref class PdfSignatureInformation : public Vintasoft.Imaging.Pdf.Tree.PdfTreeNodeBase^
If this signature must be verified, create PKCS signature object using the GetSignature method and verify signature using the Verify method.
If signature does not cover the whole document, i.e. the SignatureCoversWholeDocument method returns false, check the subsequent changes using the GetDocumentChanges method.
Here is an example that shows how to display an information about the digital signatures and verify the digital signatures of PDF document:
''' <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
/// <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; }
System.Object
 Vintasoft.Imaging.Pdf.Tree.PdfTreeNodeBase
   Vintasoft.Imaging.Pdf.Tree.DigitalSignatures.PdfSignatureInformation
Target Platforms: .NET9; .NET 8; .NET 7; .NET 6; .NET Framework 4.8, 4.7, 4.6, 4.5, 4.0, 3.5
PdfSignatureInformation Members
Vintasoft.Imaging.Pdf.Tree.DigitalSignatures Namespace
PdfPkcsSignature
SignatureInfo