如何使用AddDigitalSignatureOriginPart(DocumentFormat.OpenXml库)保护Excel文件的安全?

问题描述 投票:0回答:1

需要创建数字签名的excel文件,然后在C#中上传后验证签名。

openxml digital-signature
1个回答
0
投票

仅靠SpreadsheetDocument.AddDigitalSignatureOriginPart()方法不能保护Excel文件。 WordprocessingDocumentPresentationDocument类的相应方法也是如此。这些方法仅添加一个空的DigitalSignatureOriginPart作为一个或多个XmlSignaturePart实例的来源,每个实例均包含基于W3C建议ds:Signature(XMLDSIG)的XML Signature Syntax and Processing Version 1.1元素。

[要保护Excel文件或任何基于开放包装约定(OPC)的文件,最直接的方法是使用PackageDigitalSignatureManager类,该类包含在System.IO.Packaging提供的WindowsBase.dll命名空间中部件。因此,如果您以完整的.NET Framework为目标(例如net471),则可以使用它。但是,如果目标是.Net Core,则需要自己实现该功能。

下面的代码示例演示如何使用PackageDigitalSignatureManager类:

using System;
using System.Collections.Generic;
using System.IO.Packaging;
using System.Linq;

namespace CodeSnippets.Windows.IO.Packaging
{
    public static class DigitalSignatureManager
    {
        public static void Sign(Package package)
        {
            var dsm = new PackageDigitalSignatureManager(package)
            {
                CertificateOption = CertificateEmbeddingOption.InSignaturePart
            };

            List<Uri> parts = package.GetParts()
                .Select(part => part.Uri)
                .Concat(new[]
                {
                    // Include the DigitalSignatureOriginPart and corresponding
                    // relationship part, since those will only be added when
                    // signing.
                    dsm.SignatureOrigin,
                    PackUriHelper.GetRelationshipPartUri(dsm.SignatureOrigin)
                })
                .ToList();

            dsm.Sign(parts);
        }

        public static VerifyResult VerifySignature(Package package)
        {
            var dsm = new PackageDigitalSignatureManager(package);
            return dsm.VerifySignatures(true);
        }
    }
}

如果您需要自己实现该功能,可以帮助您熟悉许多资源:

基于这些资源,我创建了一个与.Net Core一起使用的部分示例实现。以下代码片段显示了void Sign(OpenXmlPackage, X509Certificate2)方法,该方法采用OpenXmlPackageX509Certificate2并创建有效的签名:

        public static void Sign(OpenXmlPackage openXmlPackage, X509Certificate2 certificate)
        {
            if (openXmlPackage == null) throw new ArgumentNullException(nameof(openXmlPackage));
            if (certificate == null) throw new ArgumentNullException(nameof(certificate));

            RSA privateKey = certificate.GetRSAPrivateKey();
            using SHA256 hashAlgorithm = SHA256.Create();

            // Create KeyInfo.
            var keyInfo = new KeyInfo();
            keyInfo.AddClause(new KeyInfoX509Data(certificate));

            // Create a Signature XmlElement.
            var signedXml = new SignedXml { SigningKey = privateKey, KeyInfo = keyInfo };
            signedXml.Signature.Id = Constants.PackageSignatureId;
            signedXml.SignedInfo.SignatureMethod = Constants.SignatureMethod;
            signedXml.AddReference(CreatePackageObjectReference());
            signedXml.AddObject(CreatePackageObject(openXmlPackage.Package, hashAlgorithm));
            signedXml.ComputeSignature();
            XmlElement signature = signedXml.GetXml();

            // Get or create the DigitalSignatureOriginPart.
            DigitalSignatureOriginPart dsOriginPart =
                openXmlPackage.GetPartsOfType<DigitalSignatureOriginPart>().FirstOrDefault() ??
                openXmlPackage.AddNewPart<DigitalSignatureOriginPart>();

            var xmlSignaturePart = dsOriginPart.AddNewPart<XmlSignaturePart>();

            // Write the Signature XmlElement to the XmlSignaturePart.
            using Stream stream = xmlSignaturePart.GetStream(FileMode.Create, FileAccess.Write);
            using XmlWriter writer = XmlWriter.Create(stream);
            signature.WriteTo(writer);
        }

上述void Sign(OpenXmlPackage, X509Certificate2)方法的完整源代码可以在我的CodeSnippets GitHub存储库中找到。在CodeSnippets项目中寻找DigitalSignatureManager类。

© www.soinside.com 2019 - 2024. All rights reserved.