C# 以证书签署PDF文件

C# 以证书签署PDF文件,c#,pdf,certificate,syncfusion,signing,C#,Pdf,Certificate,Syncfusion,Signing,我正在尝试使用Syncfusion对PDF文档进行数字签名。(用于生成pdf文档的库) 整个文档,而不仅仅是字段。 我对签名或证书一无所知我知道证书属于HSM类型,所以我使用了: 它在我的开发PC上工作,但在生产中不工作。找不到证书,但在签署文档时会导致: CryptographicException: Unknown error „-1073741823“ at System.Security.Cryptography.Pkcs.SignedCms.Sign(CmsSigner signer

我正在尝试使用Syncfusion对PDF文档进行数字签名。(用于生成pdf文档的库)
整个文档,而不仅仅是字段。 我对签名或证书一无所知
我知道证书属于HSM类型,所以我使用了:

它在我的开发PC上工作,但在生产中不工作。找不到证书,但在签署文档时会导致:

CryptographicException: Unknown error „-1073741823“ at System.Security.Cryptography.Pkcs.SignedCms.Sign(CmsSigner signer, Boolean silent)
我的代码:

using Syncfusion.Licensing;
using Syncfusion.Pdf;
using Syncfusion.Pdf.Graphics;
using Syncfusion.Pdf.Parsing;
using Syncfusion.Pdf.Security;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;

namespace SyncfusionTest3
{
    class Program
    {
        public static X509Certificate2 infoCertifikat = null;

        static void Main(string[] args)
        {


            var store = new System.Security.Cryptography.X509Certificates.X509Store(StoreLocation.LocalMachine);
            string thumbprint = "9F.."; //Production


            store.Open(OpenFlags.ReadOnly);

            foreach (var mCert in store.Certificates)
            {
                if (mCert.Thumbprint.ToUpper().Equals(thumbprint.ToUpper()))
                    infoCertifikat = mCert;
            }

            

            if (infoCertifikat == null)
            {
                Console.WriteLine("404 Certificate not found");
                Console.ReadKey();
                return;
            }


            string licenceKey = "LicenceKey";
            SyncfusionLicenseProvider.RegisterLicense(licenceKey);


            using (var pdfDoc = new PdfLoadedDocument("document.pdf"))
            {

                pdfDoc.DocumentInformation.Creator = "Me";
                pdfDoc.DocumentInformation.Author = "Naxi";


                PdfCertificate pdfCertificate = new PdfCertificate(infoCertifikat);

                //Normal signing
                //Syncfusion.Pdf.Security.PdfSignature signature1 = new Syncfusion.Pdf.Security.PdfSignature(pdfDoc, pdfDoc.Pages[0], pdfCertificate, "DigitalSign");

                //External signing becouse of HSM type of certificate
                Syncfusion.Pdf.Security.PdfSignature signature1 = new Syncfusion.Pdf.Security.PdfSignature(pdfDoc, pdfDoc.Pages[0], null, "DigitalSign");
                signature1.ComputeHash += Signature_ComputeHash1;

                


                signature1.Bounds = new System.Drawing.RectangleF((6 * 25.4f / 0.352777778f), (9.3f * 25.4f / 0.352777778f), 65, 25);
                signature1.ContactInfo = "Contact";
                signature1.LocationInfo = "World";
                signature1.Reason = "I want it";


                PdfStandardFont font = new PdfStandardFont(PdfFontFamily.Helvetica, 3.8f);
                float row_height = 4.2f;

                signature1.Appearance.Normal.Graphics.DrawString("Digitally Signed by " + signature1.ContactInfo, font, PdfBrushes.Black, 0, row_height * 1);
                signature1.Appearance.Normal.Graphics.DrawString("Reason: " + signature1.Reason, font, PdfBrushes.Black, 0, row_height * 2);
                signature1.Appearance.Normal.Graphics.DrawString("Location: " + signature1.LocationInfo, font, PdfBrushes.Black, 0, row_height * 3);
                signature1.Appearance.Normal.Graphics.DrawString((DateTime.Now).ToString(), font, PdfBrushes.Black, 0, row_height * 4);


                pdfDoc.Save("document_signed.pdf");
                pdfDoc.Close(true);
            }
        }


        

        private static void Signature_ComputeHash1(object sender, PdfSignatureEventArgs ars)
        {
            //Get the document bytes

            byte[] documentBytes = ars.Data;


            SignedCms signedCms = new SignedCms(new ContentInfo(documentBytes), detached: true);


            var cmsSigner = new CmsSigner(infoCertifikat);

            //Set the digest algorithm SHA256

            //cmsSigner.DigestAlgorithm = new Oid("1.3.6.1.4.1.311.10.3.12"); //Document signing – just tried

            //cmsSigner.DigestAlgorithm = new Oid("1.2.840.113549.1.1.11"); //SHA256RSA
            //cmsSigner.DigestAlgorithm = new Oid("1.2.840.113549.1.1.5"); //SHA1RSA
            //cmsSigner.DigestAlgorithm = new Oid("1.3.14.3.2.26"); //SHA1


            cmsSigner.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1"); //SHA256
            


            cmsSigner.IncludeOption = X509IncludeOption.EndCertOnly; //Without this it throws CryptographicException: A certificate chain could not be bulit to a trusted root authority. (only in production)

            signedCms.ComputeSignature(cmsSigner);
            

            //Embed the encoded digital signature to the PDF document

            ars.SignedData = signedCms.Encode();

        }
    }
}
我尝试使用不同的算法。(用代码注释)但我不知道该用哪一个。
我正在为平台目标x64构建它,因为没有它会导致:

CryptographicException: The keyset is not defined. at System.Security.Cryptography.Pkcs.PkcsUtils.CreateSignerEncodeInfo(CmsSigner signer, Boolean silent, DafeCryptoProvHandle)
生产过程中使用了经过审查的证书:


我在开发上的证书有一个关键用法:签名文档,这在生产中是不存在的。 或者增强的密钥使用缺少什么

谢谢你的建议

更新: 所以,我以不同的方式迈出了一小步,看起来很有希望,但不是穆奇

  • 我尝试了Syncfusion的正常签名并设置了CryptographicsStandard.CADES
  • 它生成签名文档并使程序崩溃。无一例外

  • 我看了看前段时间使用的way,发现它是用hashSHA1、RSA+PKCS#1签名的
  • 所以,我尝试用外部方式使用oid:

    cmsSigner.DigestAlgorithm = new Oid("1, 3, 36, 3, 3, 1, 1"); //RSA + SHA1
    
    这导致:加密异常:对象标识符的格式不正确。在SignedCms.Sign(…)

  • 我的另一种方式是侵犯同事,所以我们可以共同受苦
  • 我不知道我在做什么

    更新2:

    因此,正确的方法可能是将external与SHA1一起使用。签名文档可以工作,但当程序结束时,程序不会像正常情况那样关闭,而是停止工作。 microsoft应用程序certutil也是如此。 在列出证书后,它停止工作

    这是有关该证书的新信息。它在Luna提供的HSM中

    ================ Certificate 0 ================
    Serial Number: ...
    Issuer: ...
     NotBefore: ...
     NotAfter: ...
    Subject: ...
    Non-root Certificate
    Cert Hash(sha1): 9f
      Key Container = ...
      Provider = Luna enhanced RSA and AES provider for Microsoft Windows
    Private key is NOT exportable
    ERROR: Could not verify certificate public key against private key
    Revocation check skipped -- server offline
    Certificate is valid
    

    确保证书安装在正确的存储中(代码显示
    StoreLocation.LocalMachine
    )。因此,让我们首先检查存储中的证书是否正常,以及密钥是否关联和可访问

    运行以下命令列出并验证存储中的所有证书:

    certutil -verifystore MY
    
    输出应显示如下内容:

    ================ Certificate X ================
    Serial Number: ...
    Issuer: ...
     NotBefore: ...
     NotAfter: ...
    Subject: ...
    Non-root Certificate
    Cert Hash(sha1): ...
      Key Container = ...
      Unique container name: ...
      Provider = ...
    Private key is NOT exportable
    Signature test passed
    ...
    
    这将向您显示私钥关联及其提供程序,并将创建一个签名以检查密钥是否可访问

    因此,请确保为运行命令的用户以及您的应用程序授予访问密钥的权限。您可能需要通过阅读HSM用户手册或联系负责人(内部或制造商支持)来澄清这一点

    您的
    SignedCms
    代码看起来不错-对于测试,请尽可能保持简单(无摘要算法),并以小步前进

    编辑

    此外,当然,您需要信任您的证书。这意味着证书信任链已安装到证书存储

    证书可在此处找到:

    • 运行
      certlm.msc
    • 需要通过右键单击目录并选择所有任务和*导入,将其添加到受信任的根证书颁发机构*
    • 需要通过右键单击目录并选择所有任务和*导入,将其添加到中间证书颁发机构*

    这是桌面应用程序还是web应用程序?您也指的是HSM。。。证书的存储位置…?它是桌面应用程序。NETframework 4.8。有人告诉我这是HSM。它存储在其他地方,但它的制作与它在PC上的windows证书存储中集成的一样。因此,我应该能够像普通证书一样使用它。但它仍然不起作用。SignedCms.Sign(…)处出现未知错误“1073741823”,因此,正确的方法可能是将外部与SHA1一起使用”-绝对不是。就签名而言,特别是PDF签名,SHA1被破坏了,请看我在主要帖子中更新了一些进展。证书可能存储在LocalMachine中,这没关系。CertUtil是一件非常有趣的事情。它列出了证书,之后它在CertUtil.exe上崩溃并停止工作。它的行为与我在更新中描述的方式完全相同,当它签署文档时,保存文档并导致程序崩溃。在此之前,certutil显示:…私钥不可导出错误:无法根据私钥验证证书公钥不完整证书链找不到证书:CN=PostSignum Qualified CA 4…我们将与某人联系。Tha请看我的编辑。我可以帮助建立信任。certutil崩溃不好。事件日志(应用程序或系统)中是否有错误?是的,这有助于信任。谢谢。但certutil和我的应用程序在应用程序结束时仍会崩溃。我在主帖子中发布了有关证书的新信息。我们正试图通过HSM提供商和服务器提供商解决此问题。有点复杂。你能看一下事件日志(
    eventvwr.msc
    )在certutil崩溃后,并提供错误消息的详细信息?是的,没有什么特别的,只是崩溃。在我的测试应用程序中,它发生在MSVCP.dll中。HSM提供程序承认,证书存在问题。我们将重新安装所有服务器。这可能结束。
    ================ Certificate X ================
    Serial Number: ...
    Issuer: ...
     NotBefore: ...
     NotAfter: ...
    Subject: ...
    Non-root Certificate
    Cert Hash(sha1): ...
      Key Container = ...
      Unique container name: ...
      Provider = ...
    Private key is NOT exportable
    Signature test passed
    ...