officefileapi-405733-spreadsheet-document-api-document-security-sign-excel-files.md
The Spreadsheet Document API supports signatures in the following Microsoft Excel document formats:
The DocumentSigner class methods allow you to apply, validate, and remove digital signatures.
Important
You need a license for the DevExpress Office File API Subscription or DevExpress Universal Subscription to use this library in production code.
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 SignatureOptions class object allows you to specify validation data (certificate, hash algorithm, timestamp, etc.). Pass the SignatureInfo object as the method’s signatureInfo parameter to define the signer information.
The options and signatureInfo parameters cannot be null.
View Example: Sign an Excel Workbook and Validate the Signature
using DevExpress.Office.DigitalSignatures;
using System;
using System.Diagnostics;
using System.Security.Cryptography.X509Certificates;
static void Main(string[] args) {
//Apply a signature:
string workbookOutput = "Workbook_signed.xlsx";
SignDocument("Template.xlsx", workbookOutput);
}
static void SignDocument(string path, string output) {
DocumentSigner documentSigner = new DocumentSigner();
SignatureOptions signatureOptions = CreateSignatureOptions();
SignatureInfo signatureInfo = CreateSignatureInfo();
documentSigner.Sign(path, output, signatureOptions, signatureInfo);
Process.Start(output);
}
//Specify a signature certificate and digest method:
static SignatureOptions CreateSignatureOptions() {
X509Certificate2 certificate =
new X509Certificate2("Certificate/SignDemo.pfx", "dxdemo");
SignatureOptions options = new SignatureOptions();
options.Certificate = certificate;
options.DigestMethod = HashAlgorithmType.SHA256;
//In this example, certificate validation is skipped
options.SignatureFlags &= ~SignatureFlags.ValidateCertificate;
options.CertificateKeyUsageFlags = X509KeyUsageFlags.None;
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;
}
Imports DevExpress.Office.DigitalSignatures
Imports System
Imports System.Diagnostics
Imports System.Security.Cryptography.X509Certificates
Shared Sub Main(ByVal args() As String)
'Apply a signature:
Dim workbookOutput As String = "Workbook_signed.xlsx"
SignDocument("Template.xlsx", workbookOutput)
End Sub
Shared Sub SignDocument(ByVal path As String, ByVal output As String)
Dim documentSigner As New DocumentSigner()
Dim signatureOptions As SignatureOptions = CreateSignatureOptions()
Dim signatureInfo As SignatureInfo = CreateSignatureInfo()
documentSigner.Sign(path, output,signatureOptions, signatureInfo)
Process.Start(output)
End Sub
'Specify a signature certificate and digest method:
Shared Function CreateSignatureOptions() As SignatureOptions
Dim certificate As New X509Certificate2("Certificate/SignDemo.pfx", "dxdemo")
Dim options As New SignatureOptions()
options.Certificate = certificate
options.DigestMethod = HashAlgorithmType.SHA256
'In this example, certificate validation is skipped
options.SignatureFlags = options.SignatureFlags And Not SignatureFlags.ValidateCertificate
options.CertificateKeyUsageFlags = X509KeyUsageFlags.None
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
Run Demo: Spreadsheet Document Signature
Call the DocumentSigner.Validate method to validate a signature in the specified file or stream.
The SignatureValidationOptions object allows you to specify signature validation options (signature or timestamp certificate policy, decryption password, etc.). Use the SignatureValidationOptions.ValidationFlags property to exclude validation steps.
View Example: Sign an Excel Workbook and Validate the Signature
using DevExpress.Office.DigitalSignatures;
using System.Diagnostics;
using System.Net;
static void Main(string[] args) {
ValidateSignature("Template_signed.xlsx");
}
private static void ValidateSignature(string path) {
DocumentSigner validator = new DocumentSigner();
//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);
}
Imports Microsoft.VisualBasic
Imports DevExpress.Office.DigitalSignatures
Imports System.Diagnostics
Imports System.Net
Shared Sub Main(ByVal args() As String)
ValidateSignature("Template_signed.xlsx")
End Sub
Private Shared Sub ValidateSignature(ByVal path As String)
Dim validator As New DocumentSigner()
'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
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 document to be validated is encrypted, specify the SignatureValidationOptions.DecryptionPassword property to decrypt the document. Otherwise, the Result property returns PackageSignatureValidationResult.PackageOpenFailed.
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:
| Property | Description |
|---|---|
| SignatureValidationInfo.PassedChecks | Returns verification types the signature passed. |
| SignatureValidationInfo.PassedCheckDetails | Obtains information about passed verifications. |
| SignatureValidationInfo.FailedChecks | Returns verification types the signature did not pass. |
| SignatureValidationInfo.FailedCheckDetails | Retrieves information about failed verifications. |
| SignatureValidationInfo.CheckDetails | Gets information about all verifications. |
The following code snippet analyzes the validation result and shows information in the console:
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;
}
}
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
Call the DocumentSigner.RemoveSignatures method to clear signatures from a document and save the result.
static void Main(string[] args) {
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);
}
Shared Sub Main(ByVal args() As String)
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