如何用我的私人pfx密钥签署excel?

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

c#如何用我的私有pfx密钥签署excel?您能否解释一下Excel文件的哪一部分需要签名?

// this is our private key array read directly pfx file
byte[] pfkArray = {};

// this is our excel file
byte[] xlsArray = {};

xlsArray的哪个/哪个部分需要签名? xlsArray的所有文件或某些段/扇区? RFC?

在这里,我们可以使用一些介绍/类来签署有关RFC要求的文档。

using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Web;

namespace Infra
{
    public class SignFile
    {

        private const string ConstLocalRootSerial = @"1c151322b969b79047f5c5d90cb";          
        private const string ConstLocalSerial = @"1c041d12ac33528847ac378283";

        private RSACryptoServiceProvider _key;
        private readonly X509Certificate2 _publicCert;

        public X509Certificate2Collection Certificates
        {
            get
            {
                X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
                store.Open(OpenFlags.ReadOnly);
                return store.Certificates;
            }
        }

        /// <summary>
        /// Sign file/document/stream/bytes
        /// </summary>
        /// <param name="inputData">some data to sign -> byte[] data = new byte[1024];</param>
        /// <param name="signature"></param>
        /// <returns>signed data</returns>
        public byte[] GetSignature(byte[] inputData)
        {
            //Sign the data
            byte[] signature = _key.SignData(inputData, CryptoConfig.MapNameToOID("SHA256"));
            return signature;
        }

        /// <summary>
        /// Validate after sign was completed
        /// </summary>
        /// <param name="inputData"></param>
        /// <param name="signature">signed data</param>
        /// <returns>true if data was signed</returns>
        public bool ValidateSignature(byte[] inputData, byte[] signature)
        {
            _key = (RSACryptoServiceProvider)_publicCert.PublicKey.Key;
            if (!_key.VerifyData(inputData, CryptoConfig.MapNameToOID("SHA256"), signature))
                throw new CryptographicException();

            return true;
        }


        public X509Certificate2 Open()
        {

            var certificates = Certificates;
            foreach (X509Certificate2 certificate in certificates)
            {
                // TODO: Just change it for BETA/FT/PROD
                if (certificate.SerialNumber.ToUpper() == ConstLocalSerial.ToUpper())
                {
                    return certificate;
                }
            }

            throw new CryptographicException("Certificate serial number is missing from authority");
        }


        public SignFile()
        {                      
            _publicCert = Open();                  
            _key = new RSACryptoServiceProvider();
            _key.FromXmlString(_publicCert.PrivateKey.ToXmlString(true));
        }

        /// <summary>
        /// Sign file with my private key
        /// </summary>
        /// <param name="cer">file path to cer file @"C:\mycertificate.cer"        
        /// string certificateFile  = HttpContext.Current.Server.MapPath("~/App_Data/internal.provident.l.cer");
        /// string certificateFile2 = HttpContext.Current.Request.MapPath("~/internal.provident.l.cer");
        /// </param>
        public SignFile(string pfx)
        {                   
            _publicCert = new X509Certificate2(pfx);           
            X509Certificate2 privateCert = null;
            X509Store store = new X509Store(StoreLocation.LocalMachine);
            store.Open(OpenFlags.ReadOnly);
            foreach (X509Certificate2 cert in store.Certificates)
            {
                if (cert.GetCertHashString() == _publicCert.GetCertHashString())
                    privateCert = cert;
            }

            //Round-trip the key to XML and back, there might be a better way but this works
            _key = new RSACryptoServiceProvider();
            _key.FromXmlString(privateCert.PrivateKey.ToXmlString(true));
        }

    }

}

这是我不想做的事情


         // Let me first get excel data    
         string excelFilePath = @"/myexcel.xls";
         FileStream f = new FileStream(excelFilePath, FileMode.Open);
         byte[] xlsArray = f.StreamToByteArray();

         // Now we can get private key     
         string certFilePath = @"/certi.pfx";
         FileStream f2 = new FileStream(certFilePath, FileMode.Open);
         byte[] pfkArray = f.StreamToByteArray();

         // Prepare for sign data
         var signer = new SignFile();
         // the problems here are:
         //  - we need to not use SHA256 
         //  - should we need to pass entire xlsArray array???
         byte[] signedData = signer.GetSignature(xlsArray);
c# excel certificate rfc
1个回答
1
投票

您不能只加载字节并签名。该文件是OLE Streams的构建,需要进行哈希处理,并且签名结构也会持久保存到OLE流...

这是官方文档:https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-offcrypto/2770c801-5f0f-4326-89e8-d6ef15b68ef1

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