如何使用DocumentFormat.OpenXml的AddDigitalSignatureOriginPart实现Excel签名及上传验证(C#)
Got it, let's break this down into two core parts: adding a digital signature to an Excel file, then verifying that signature once the file is uploaded. I'll use the DocumentFormat.OpenXml library (the official OpenXML SDK for .NET) for both tasks.
Part 1: Adding a Digital Signature to an Excel File
First, make sure you have the necessary NuGet packages installed:
DocumentFormat.OpenXml- For .NET Framework, you might also need
WindowsBase(but .NET Core/.NET 5+ includes this with the OpenXML package).
You'll also need an X.509 certificate—use a self-signed one for testing, or a valid CA-issued certificate for production.
Here's the code to sign an Excel file:
using DocumentFormat.OpenXml.Packaging; using System.Security.Cryptography.X509Certificates; public static void SignExcelFile(string inputFilePath, string outputFilePath, string certificatePath, string certificatePassword) { // Load the certificate (exportable flag lets the SDK use it for signing) var certificate = new X509Certificate2( certificatePath, certificatePassword, X509KeyStorageFlags.Exportable ); // Open the Excel file in read-write mode using (var spreadsheetDocument = SpreadsheetDocument.Open(inputFilePath, true)) { // Add the required DigitalSignatureOriginPart—this stores all signature data in the package var signatureOriginPart = spreadsheetDocument.AddDigitalSignatureOriginPart(); signatureOriginPart.PackageDigitalSignatureManager.Certificate = certificate; // Create a signature object and add optional metadata var signature = signatureOriginPart.PackageDigitalSignatureManager.CreateSignature(); signature.SignatureComments.Add("This file is digitally signed to ensure integrity and authenticity."); // Commit the signature to the file signatureOriginPart.PackageDigitalSignatureManager.Sign(signature); // Save changes and close the document spreadsheetDocument.Save(); } }
Quick Tips for Testing:
- Generate a self-signed certificate with PowerShell:
New-SelfSignedCertificate -Type DocumentEncryptionCert -Subject "CN=Your Test Name" -KeyExportPolicy Exportable -CertStoreLocation "Cert:\CurrentUser\My" - Always use
usingstatements to ensure theSpreadsheetDocumentis properly disposed of (prevents file locks).
Part 2: Verifying the Digital Signature After Upload
Once the signed Excel file is uploaded (via an API, form upload, etc.), you need to validate two things: that the file hasn't been tampered with, and that the signing certificate is trusted.
Here's the verification code:
using DocumentFormat.OpenXml.Packaging; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; public static bool VerifyExcelSignature(Stream uploadedFileStream) { // Open the uploaded file in read-only mode to avoid modifying it using (var spreadsheetDocument = SpreadsheetDocument.Open(uploadedFileStream, false)) { // Check if the file has a signature container var signatureOriginPart = spreadsheetDocument.DigitalSignatureOriginPart; if (signatureOriginPart == null) { Console.WriteLine("No digital signature found in the Excel file."); return false; } var signatureManager = signatureOriginPart.PackageDigitalSignatureManager; var signatures = signatureManager.Signatures; if (signatures.Count == 0) { Console.WriteLine("No valid signatures present in the file."); return false; } // Validate each signature in the file foreach (var signature in signatures) { try { // Check if the file content was altered since signing bool isContentUntampered = signature.Verify(); // Check if the certificate is trusted (skip this for self-signed test certs) var signerCert = signature.SignerCertificate; bool isCertificateTrusted = signerCert.Verify(); if (!isContentUntampered || !isCertificateTrusted) { Console.WriteLine( $"Signature invalid. Tampered: {!isContentUntampered}, " + $"Certificate untrusted: {!isCertificateTrusted}" ); return false; } } catch (CryptographicException ex) { Console.WriteLine($"Signature verification failed: {ex.Message}"); return false; } } Console.WriteLine("All digital signatures are valid and trusted."); return true; } }
Key Verification Notes:
signature.Verify()checks the file's hash against the signed hash—any change to the Excel content (even a single cell) will make this fail.signerCert.Verify()validates that the certificate is issued by a trusted CA and hasn't expired. For self-signed certs, add the cert to your trusted root store or skip this check for testing.
Usage Examples
Signing a Local File:
SignExcelFile( inputFilePath: @"C:\temp\unsigned.xlsx", outputFilePath: @"C:\temp\signed.xlsx", certificatePath: @"C:\temp\test-cert.pfx", certificatePassword: "your-secure-password" );
Verifying an Uploaded File (ASP.NET Core Example):
[HttpPost("upload-excel")] public IActionResult UploadAndVerify(IFormFile file) { if (file == null || file.Length == 0) return BadRequest("No file was uploaded."); using (var stream = file.OpenReadStream()) { bool isSignatureValid = VerifyExcelSignature(stream); return isSignatureValid ? Ok("File signature is valid and untampered.") : BadRequest("Invalid or tampered file."); } }
内容的提问来源于stack exchange,提问作者saloni

