Back to Devexpress

DocumentSigner Class

officefileapi-devexpress-dot-office-dot-digitalsignatures.md

latest14.8 KB
Original Source

DocumentSigner Class

Allows you to sign Office documents and validate signatures.

You need an active DevExpress Office File API Subscription or DevExpress Universal Subscription to use these methods in production code.

Namespace : DevExpress.Office.DigitalSignatures

Assembly : DevExpress.Docs.v25.2.dll

NuGet Package : DevExpress.Document.Processor

Declaration

csharp
[DXLicenseDocs]
public class DocumentSigner
vb
<DXLicenseDocs>
Public Class DocumentSigner

Remarks

To use the DocumentSigner class methods, add a reference to the DevExpress.Docs.v25.2.dll assembly. If you use this assembly in production code, a license for the DevExpress Office File API or DevExpress Universal Subscription is required. For more information, refer to the following page: DevExpress Subscription Plans.

Sign Documents

Use the DocumentSigner.Sign method to sign documents and save the result. You can use XAdES-BES and XAdES-T signatures with X.509 certificates. The following formats are available:

  • Microsoft Word

    • Open XML (DOCX, DOTX, DOTM, DOCM)
    • 97-2003 (DOC, DOT)
  • Microsoft Excel

    • Open XML (XLSX, XLTX, XLSM)
    • 97-2003 binary file (XLS, XLT)
  • Microsoft PowerPoint

    • PPTX, PPT

The SignatureOptions class object allows you to specify validation data (certificate, hash algorithm, timestamp, etc.). Pass the SignatureInfo object to define the signer information.

The options and signatureInfo parameters cannot be null.

The code sample below signs and saves a Word and Excel document:

csharp
using DevExpress.Office.DigitalSignatures;
using System;
using System.Diagnostics;
using System.Security.Cryptography.X509Certificates;

static void Main(string[] args)
{
    //Sign a workbook:
    SignDocument("Template.xlsx", "Workbook_signed.xlsx");

    //Sign a document:
    SignDocument("Template.docx", "Template_signed.docx");
}
static void SignDocument(string path, string output)
{
    DocumentSigner documentSigner = new DocumentSigner();
    documentSigner.Sign(path, output,
     CreateSignatureOptions(), CreateSignatureInfo());
}

//Specify a signature certificate and digest method:
static SignatureOptions CreateSignatureOptions()
{
    X509Certificate2 certificate = new X509Certificate2("Certificate/SignDemo.pfx", "dxdemo");
    Uri tsaServer = new Uri("https://freetsa.org/tsr");
    SignatureOptions options = new SignatureOptions();
    options.Certificate = certificate;
    if (tsaServer != null)
        options.TsaClient = new TsaClient(tsaServer, HashAlgorithmType.SHA256);

    //In this example, certificate validation is skipped
    options.SignatureFlags &= ~SignatureFlags.ValidateCertificate;
    options.CertificateKeyUsageFlags = X509KeyUsageFlags.None;
    options.DigestMethod = HashAlgorithmType.SHA256;

    X509ChainPolicy policy = new X509ChainPolicy();
    policy.RevocationMode = X509RevocationMode.NoCheck;
    policy.RevocationFlag = X509RevocationFlag.ExcludeRoot;
    policy.VerificationFlags |= X509VerificationFlags.AllowUnknownCertificateAuthority |
        X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown;
    options.CertificatePolicy = policy;
    options.TimestampCertificatePolicy = policy;
    return options;
}

//Specify signer information:
static SignatureInfo CreateSignatureInfo()
{
    SignatureInfo signatureInfo = new SignatureInfo();
    signatureInfo.CommitmentType = CommitmentType.ProofOfApproval;
    signatureInfo.Time = DateTime.UtcNow;
    signatureInfo.ClaimedRoles.Clear();
    signatureInfo.ClaimedRoles.Add("Sales Representative");
    signatureInfo.Comments = "Demo Digital Signature";

    return signatureInfo;
}
vb
Imports DevExpress.Office.DigitalSignatures
Imports System
Imports System.Diagnostics
Imports System.Security.Cryptography.X509Certificates

Shared Sub Main(ByVal args() As String)
    'Sign a workbook:
    SignDocument("Template.xlsx", "Workbook_signed.xlsx")

    'Sign a document:
    SignDocument("Template.docx", "Document_signed.docx")
End Sub

Shared Sub SignDocument(ByVal path As String, ByVal output As String)
    Dim documentSigner As New DocumentSigner()
    documentSigner.Sign(path, output,
     CreateSignatureOptions(), CreateSignatureInfo())
    Process.Start(output)
End Sub

' Specify a signature certificate and digest method:
Private Shared Function CreateSignatureOptions() As SignatureOptions
    Dim certificate As New X509Certificate2("Certificate/SignDemo.pfx", "dxdemo")
    Dim tsaServer As New Uri("https://freetsa.org/tsr")
    Dim options As New SignatureOptions()
    options.Certificate = certificate
    If tsaServer IsNot Nothing Then
        options.TsaClient = New TsaClient(tsaServer, HashAlgorithmType.SHA256)
    End If

    'In this example, certificate validation is skipped
    options.SignatureFlags = options.SignatureFlags And Not SignatureFlags.ValidateCertificate
    options.CertificateKeyUsageFlags = X509KeyUsageFlags.None
    options.DigestMethod = HashAlgorithmType.SHA256

    Dim policy As New X509ChainPolicy()
    policy.RevocationMode = X509RevocationMode.NoCheck
    policy.RevocationFlag = X509RevocationFlag.ExcludeRoot
    policy.VerificationFlags = policy.VerificationFlags Or X509VerificationFlags.AllowUnknownCertificateAuthority Or X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown
    options.CertificatePolicy = policy
    options.TimestampCertificatePolicy = policy
    Return options
End Function

' Specify signer information:
Shared Function CreateSignatureInfo() As SignatureInfo
    Dim signatureInfo As New SignatureInfo()
    signatureInfo.CommitmentType = CommitmentType.ProofOfApproval
    signatureInfo.Time = Date.UtcNow
    signatureInfo.ClaimedRoles.Clear()
    signatureInfo.ClaimedRoles.Add("Sales Representative")
    signatureInfo.Comments = "Demo Digital Signature"

    Return signatureInfo
End Function

Validate Signatures

Call the DocumentSigner.Validate method to validate document signatures. The SignatureValidationOptions object allows you to specify signature validation options. Use the SignatureValidationOptions.ValidationFlags property to exclude validation steps.

csharp
private static void ValidateSignature(string path)
{
    DocumentSigner validator = new DocumentSigner();

    //Specify validation options
    //In this example, certificate validation
    //is skipped
    SignatureValidationOptions validationOptions = new SignatureValidationOptions();
    validationOptions.ValidationFlags = ~ValidationFlags.ValidateSignatureCertificate & ~ValidationFlags.ValidateTimestampCertificate;

    //Validate the signature:
    PackageSignatureValidation signatureValidation = validator.Validate(path, validationOptions);
    AnalyzeValidationResult(signatureValidation);

}
vb
Private Shared Sub ValidateSignature(ByVal path As String)
  Dim validator As New DocumentSigner()

  'Specify validation options
  'In this example, certificate validation
  'is skipped
  Dim validationOptions As New SignatureValidationOptions()
  validationOptions.ValidationFlags = (Not ValidationFlags.ValidateSignatureCertificate) And Not ValidationFlags.ValidateTimestampCertificate

  'Validate the signature:
  Dim signatureValidation As PackageSignatureValidation = validator.Validate(path, validationOptions)
  AnalyzeValidationResult(signatureValidation)
End Sub

Validation Process

The Validate method returns the PackageSignatureValidation instance that contains validation information. Check the PackageSignatureValidation.Result and PackageSignatureValidation.ResultMessage properties to determine whether the signature is valid.

Note

Make sure that the signature certificate is registered on your machine. Otherwise, the signature is invalid.

If the document is not signed, the PackageSignatureValidation.Result property returns SignaturesNotFound. If the PackageSignatureValidation.Result property returns Invalid or PartiallyValid, check the PackageSignatureValidation.Items property to obtain a list of items with detailed validation information. The number of SignatureValidationInfo objects in the list is equal to the number of signatures.

The table below lists API used to obtain information:

PropertyDescription
SignatureValidationInfo.PassedChecksReturns verification types the signature passed.
SignatureValidationInfo.PassedCheckDetailsObtains information about passed verifications.
SignatureValidationInfo.FailedChecksReturns verification types the signature did not pass.
SignatureValidationInfo.FailedCheckDetailsRetrieves information about failed verifications.
SignatureValidationInfo.CheckDetailsGets information about all verifications.

The code sample below analyzes the validation result and shows information in the console:

csharp
private static void AnalyzeValidationResult(PackageSignatureValidation signatureValidation)
{
    string validationMessage = signatureValidation.ResultMessage;

    //Check validation result and show information in the console:
    switch (signatureValidation.Result)
    {
        case PackageSignatureValidationResult.Valid:
            Console.WriteLine(validationMessage); Console.ReadKey();
            Process.Start(output);
            break;

        case PackageSignatureValidationResult.SignaturesNotFound:
            Console.WriteLine(validationMessage);
            break;

        case PackageSignatureValidationResult.Invalid:
        case PackageSignatureValidationResult.PartiallyValid:
            var failedCheckDetails = signatureValidation.Items[0].FailedCheckDetails;
            Console.WriteLine(validationMessage);
            int i = 1;
            foreach (SignatureCheckResult checkResult in failedCheckDetails)
            {
                Console.WriteLine(String.Format("Validation details {0}: \r\n" +
                    "{1} failed, Info: {2} \r\n", i, checkResult.CheckType, checkResult.Info));
                i++;
            }
            Console.ReadKey();
            break;
    }
}
vb
Private Shared Sub AnalyzeValidationResult(ByVal signatureValidation As PackageSignatureValidation)
  Dim validationMessage As String = signatureValidation.ResultMessage

  'Check validation result and show information in the console:
  Select Case signatureValidation.Result
    Case PackageSignatureValidationResult.Valid
      Console.WriteLine(validationMessage)
      Console.ReadKey()
      Process.Start(output)

    Case PackageSignatureValidationResult.SignaturesNotFound
      Console.WriteLine(validationMessage)

    Case PackageSignatureValidationResult.Invalid, PackageSignatureValidationResult.PartiallyValid
      Dim failedCheckDetails = signatureValidation.Items(0).FailedCheckDetails
      Console.WriteLine(validationMessage)
      Dim i As Integer = 1
      For Each checkResult As SignatureCheckResult In failedCheckDetails
        Console.WriteLine(String.Format("Validation details {0}: " & ControlChars.CrLf & "{1} failed, Info: {2} " & ControlChars.CrLf, i, checkResult.CheckType, checkResult.Info))
        i += 1
      Next checkResult
      Console.ReadKey()
  End Select
End Sub

Remove Signatures

Utilize the DocumentSigner.RemoveSignatures method to clear signatures from a document and save the result.

csharp
static void Main(string[] args)
{
    ClearSignatures("Template_signed.docx", @"D:/Template_cleared.docx");
    ClearSignatures("Template_signed.xlsx", @"D:/Template_cleared.xlsx");
}

  private static void ClearSignatures(string path, string output)
  {
      DocumentSigner remover = new DocumentSigner();
      remover.RemoveSignatures(path, output);
      Process.Start(output);
  }
vb
Shared Sub Main(ByVal args() As String)
  ClearSignatures("Template_signed.docx", "D:/Template_cleared.docx")
  ClearSignatures("Template_signed.xlsx", "D:/Template_cleared.xlsx")
End Sub

  Private Shared Sub ClearSignatures(ByVal path As String, ByVal output As String)
    Dim remover As New DocumentSigner()
    remover.RemoveSignatures(path, output)
    Process.Start(output)
  End Sub

Inheritance

Object DocumentSigner

See Also

DocumentSigner Members

DevExpress.Office.DigitalSignatures Namespace