简体   繁体   English

通过证书签署 PDF 文档

[英]Signing PDF document by certificate

Im trying digitaly sign PDF document with Syncfusion.我正在尝试使用 Syncfusion 对 PDF 文档进行数字签名。 (Library for generating pdf document) (生成pdf文档的库)
Entire document, not just field.整个文档,而不仅仅是字段。 I don't know mutch about signing or certificates.我对签名或证书一无所知。
I know that certificate is type of HSM, so i used: Syncfusion - Externally sign a pdf document我知道证书是 HSM 的类型,所以我使用了: Syncfusion - Externally sign a pdf 文档

It works on my development PC, but doesn't in production.它适用于我的开发 PC,但不适用于生产。 Certificate is find, but at signing document it causes:找到证书,但在签署文件时会导致:

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

My code:我的代码:

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();

        }
    }
}

I tried use different DigestAlgorithm.我尝试使用不同的 DigestAlgorithm。 (commented in code) But i dont't know which i should use. (在代码中注释)但我不知道我应该使用哪个。
Im building it for Platform target x64 because without it it causes:我为 Platform target x64 构建它,因为没有它会导致:

CryptographicException: The keyset is not defined. at System.Security.Cryptography.Pkcs.PkcsUtils.CreateSignerEncodeInfo(CmsSigner signer, Boolean silent, DafeCryptoProvHandle)

There is censored certificate used on production:生产中使用了经过审查的证书:

证书图片

My certificates on develop have Key Usage: Signing document,which is missing on production.我的开发证书有密钥用法:签名文档,生产中缺少。 Or Enhanced Key Usage is missing something?或者增强的密钥用法缺少什么?

Thank you for any sugesstion.感谢您的任何建议。

UPDATE: So, I made i little steps in different few ways which look hopefully, but not mutch.更新:所以,我以不同的几种方式做了我的小步骤,看起来很有希望,但不是mutch。

  1. I tried Normal signing of Syncfusion and set CryptographicStandard.CADES我尝试了 Syncfusion 的正常签名并设置 CryptographicStandard.CADES
Syncfusion.Pdf.Security.PdfSignature signature1 = new Syncfusion.Pdf.Security.PdfSignature(pdfDoc, pdfDoc.Pages[0], pdfCertificate, "DigitalSign");
signature1.Settings.CryptographicStandard = CryptographicStandard.CADES;

Its make signed document and crash the program.它制作签名文件并使程序崩溃。 Like without any exception.喜欢无一例外。

  1. I looked on way, which was used some time ago and i find out, that it was signing with hashSHA1, RSA + PKCS#1.我查看了前一段时间使用的方式,我发现它正在使用 hashSHA1、RSA + PKCS#1 进行签名。

So, i tried in external way use oid:所以,我尝试以外部方式使用 oid:

cmsSigner.DigestAlgorithm = new Oid("1, 3, 36, 3, 3, 1, 1"); //RSA + SHA1

And that causes: CryptographicsException: The object identifier is poorly formatted.这会导致: CryptographicsException:object 标识符格式不正确。 at SignedCms.Sign(...)在 SignedCms.Sign(...)

  1. And another way Im triying is invating colleague, so we can suffer colletively.我尝试的另一种方法是请同事,这样我们就可以共同受苦。

I dont know what Im doing.我不知道我在做什么。

Update 2:更新 2:

So, the right way is probably using external with SHA1.所以,正确的方法可能是使用外部的 SHA1。 Signing document works, but when program ends, the program don't close like normal but stops working.签名文件有效,但是当程序结束时,程序不会像往常一样关闭,而是停止工作。 The same thing do microsoft application certutil.微软应用程序 certutil 也是如此。 After lists certificates it stops working.列出证书后,它停止工作。

This is new info about that certificate.这是关于该证书的新信息。 Its in HSM provided by Luna.它在 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

Make sure the certificate is installed in the correct store (you code shows StoreLocation.LocalMachine ).确保证书安装在正确的商店中(您的代码显示StoreLocation.LocalMachine )。 So let's first check if the certificate in the store is fine and the key is associated and accessible.所以我们先检查一下store中的证书是否正常,key是否关联且可访问。

Run the following command to list and verify all certificates in the store:运行以下命令以列出并验证存储中的所有证书:

certutil -verifystore MY

The output should show something like this: output 应该显示如下:

================ 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
...

This will show you the Private Key Association and its Provider and will create a signature to check if the key is accessible.这将向您显示私钥关联及其提供者,并将创建签名以检查密钥是否可访问。

So ensure the permission to access the key is given for the user running the command, as well as your application.因此,请确保为运行命令的用户以及您的应用程序授予访问密钥的权限。 You might need to clarify this by reading the HSM user manual or contact someone the responsible person (in-house or the manufacturer support)您可能需要通过阅读 HSM 用户手册或联系负责人(内部或制造商支持)来澄清这一点

You SignedCms code looks good - for testing keep it as simple as possible (no digest algorithm) and step forward in small steps.您的SignedCms代码看起来不错 - 对于测试,请使其尽可能简单(无摘要算法)并小步前进。

EDIT编辑

Additionally, of curse, you need to have your certificate trusted.此外,当然,您需要让您的证书受信任。 This means that the certificate trust chain is installed to the certificate store.这意味着证书信任链已安装到证书存储区。

The certificates can be found here: http://crt.postsignum.cz/certifikaty_autorit.html证书可以在这里找到: http://crt.postsignum.cz/certifikaty_autorit.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM