签署PDF时如何以编程方式输入X509Certificate2证书的PIN码(在C#中)

时间:2020-07-25 09:21:07

标签: c# cryptography digital-signature x509certificate2

我正在使用syncfusion pdf对pdf文件进行数字签名。在他们的网站上,他们有一个外部签名PDF的示例。我稍微更改了示例,以便可以从Windows证书存储区选择证书。所选证书需要PIN码,以便弹出对话框。函数Signature_ComputeHast是纯C#代码。如何在下面的代码中以编程方式输入PIN?

原始示例:https://help.syncfusion.com/file-formats/pdf/working-with-digitalsignature#externally-sing-a-pdf-document

       private static X509Certificate2 SelectCertificate()
        {
            // Selecte certificate from store
            var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
            X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
            X509Certificate2Collection selectedCertificate = (X509Certificate2Collection)collection.Find(X509FindType.FindByKeyUsage, X509KeyUsageFlags.DigitalSignature, false);// (X509FindType.FindByKeyUsage, X509KeyUsageFlags.DigitalSignature, true);
            selectedCertificate = X509Certificate2UI.SelectFromCollection(
            store.Certificates,
            "Certficates",
            "Select a certificate for signing the document",
            X509SelectionFlag.SingleSelection);
            return selectedCertificate[0];
        }


void Signature_ComputeHash(object sender, PdfSignatureEventArgs arguments)

        {
            //Get the document bytes
            byte[] documentBytes = arguments.Data;
            SignedCms signedCms = new SignedCms(new ContentInfo(documentBytes), detached: true);
            //Compute the signature using the specified digital ID file and the password
            X509Certificate2 certificate = SelectCertificate();
            var cmsSigner = new CmsSigner(certificate);
            //Set the digest algorithm SHA256
            cmsSigner.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1");
            signedCms.ComputeSignature(cmsSigner);
            //Embed the encoded digital signature to the PDF document
            arguments.SignedData = signedCms.Encode();
        }

1 个答案:

答案 0 :(得分:1)

您将需要使用RSACryptoServiceProvider或RSACng cng(在.NET核心中)类,这些类在Windows上以更高的粒度支持硬件安全模块。您可以创建带有参数的适当类的新实例,以包含如下密码:

        if(certificate.PrivateKey is RSACryptoServiceProvider rsa) {
            if(rsa.CspKeyContainerInfo.HardwareDevice) {
                CspParameters cspParams = new CspParameters(1, rsa.CspKeyContainerInfo.ProviderName,
                    rsa.CspKeyContainerInfo.UniqueKeyContainerName) {
                    KeyPassword = certPassword,
                    Flags = CspProviderFlags.NoPrompt
                };
                byte[] signedCMSBytes = new RSACryptoServiceProvider(cspParams).SignData(documentBytesDigest);
            }
        }

据我所知,在签名之前,您需要自己创建documentBytes摘要的哈希摘要,并将其与所需的经过身份验证的属性一起放入PKCS#7中。之后,您需要将所有未经身份验证的属性添加到CMS。我个人使用Bouncy Castle进行所有操作。但是我们必须使用MS SSC与OS交互才能访问HSM。对于SSC类,可能有一种方法可以做到这一切。顺便说一下,certPassword是SecureString。

相关问题