【问题标题】:Signing PDFs with iTextSharp Luna HSM - Hello world使用 iTextSharp Luna HSM 签署 PDF - Hello world
【发布时间】:2015-05-26 02:47:59
【问题描述】:

我正在尝试使用 Luna HSM 签署 PDF 并获得以下代码:

public class Sign
{
    private const string _reason = "Test seal by eSignatur";
    private const string _location = "Copenhagen, Denmark";
    private const int _estimatedSize = 0;
    private readonly X509Certificate2 _certificate;
    private readonly ICollection<X509Certificate> _chain;
    private readonly IOcspClient _ocspClient;
    private readonly ICollection<ICrlClient> _crlList;
    private readonly ITSAClient _tsaClient;

    public Sign(X509Certificate2 certificate)
    {
        _certificate = certificate;
        _chain = GetChain();
        _ocspClient = new OcspClientBouncyCastle();
        _crlList = new List<ICrlClient> { new CrlClientOnline(_chain) };
        _tsaClient = GetTsaClient(_chain);
    }

    private ICollection<X509Certificate> GetChain()
    {
        var x509Store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
        x509Store.Open(OpenFlags.ReadOnly);

        var x509Chain = new X509Chain();
        x509Chain.Build(_certificate);

        var chain = (
        from X509ChainElement x509ChainElement in x509Chain.ChainElements
        select DotNetUtilities.FromX509Certificate(x509ChainElement.Certificate)).ToList();
        x509Store.Close();
        return chain;
    }

    private ITSAClient GetTsaClient(IEnumerable<X509Certificate> chain)
    {
        return (from cert in chain
                select CertificateUtil.GetTSAURL(cert)
                    into tsaUrl
                    where tsaUrl != null
                    select new TSAClientBouncyCastle(tsaUrl)).FirstOrDefault();
    }

    public void Execute(string dest)
    {
        using (var reader = new PdfReader(GeneratePDF()))
        {
            using (var os = new FileStream(dest, FileMode.Create))
            {
                var stamper = PdfStamper.CreateSignature(reader, os, '\0');

                    var appearance = stamper.SignatureAppearance;
                    appearance.Reason = _reason;
                    appearance.Location = _location;
                    appearance.SetVisibleSignature(new Rectangle(0, 0, 0, 0), 1, string.Format("seal-{0}", DateTime.Now));

                    var pks = new X509Certificate2Signature(_certificate, DigestAlgorithms.SHA256);
                    MakeSignature.SignDetached(appearance, pks, _chain, _crlList, _ocspClient, _tsaClient, _estimatedSize, CryptoStandard.CMS);

            }
        }
    }
}

然后我引用了我已颁发的证书,它似乎已正确安装并具有相应的私钥,我可以使用certmgr.msc 查看该证书。我通过它的指纹来引用它。

 protected void Page_Load(object sender, EventArgs e)
{
    var store = new X509Store(StoreLocation.CurrentUser);     
    try
    {
        store.Open(OpenFlags.ReadOnly);
        var certificates = store.Certificates;
        X509Certificate2 cert = null;
        foreach (var certificate in certificates)
        {
            if (certificate.Thumbprint.ToString() == "123456")
            {
                cert = certificate;
            }
        }

        Sign Signer = new Sign(cert);
        Signer.Execute(string.Format(@"G:\Delete\{0}.pdf", DateTime.Now.ToString().Replace(":", "").Replace(@"/", "")));
    }
    finally 
    {
        store.Close();
    }
}

我收到以下错误:

“/iText - HSM”应用程序中的服务器错误。 未定义键集。

说明:在执行当前 Web 请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。

异常详细信息:System.Security.Cryptography.CryptographicException:未定义密钥集。

Source Error: 


Line 97:                         appearance.SetVisibleSignature(new Rectangle(0, 0, 0, 0), 1, string.Format("seal-{0}", DateTime.Now));
Line 98:                         
Line 99:                         var pks = new X509Certificate2Signature(_certificate, DigestAlgorithms.SHA256);
Line 100:                        MakeSignature.SignDetached(appearance, pks, _chain, _crlList, _ocspClient, _tsaClient, _estimatedSize, CryptoStandard.CMS);
Line 101:     

我非常感谢一些关于我应该做什么的指导,即我是否使用了正确的证书?

在此先感谢

【问题讨论】:

  • 我只知道如何在 Java 中执行此操作,但查看您的代码和错误,我会说您的机器 (@987654326) 上的密钥库 (StoreName.My) 中没有密钥@)。你确定你的 Windows 机器上有 Luna HSM 吗?我认为大多数 HSM 都在 Linux 服务器上(这是合乎逻辑的选择:我在桌面上使用 Windows;在服务器上使用 Linux)。
  • 三个问题: 1. 你在IIS上运行你的代码吗? 2.您的应用程序池使用什么身份? 3. 您的代码是否与位于同一存储但由不同 CSP 管理的其他证书一起使用(未存储在 HSM 中,但例如从 PKCS#12 文件导入)? @BrunoLowagie 在 Windows 平台上使用 HSM 实际上是很常见的做法。大多数情况下,它可以通过与大多数智能卡完全相同的 API 访问 - MS CryptoAPI 和/或 PKCS#11。
  • 您好,感谢您的快速回复。澄清一下,我正在连接到远程托管的 HSM 并安装了客户端软件。我可以确认连接。我遵循安装指南并使用 HSM 创建了 CSR,使用 CSR 从证书提供商处请求证书,并已在我的本地计算机上接收并安装了证书。
  • 试用证书显示它有一个与之关联的私钥以及链中的所有其他证书。这都是在 Windows 7-64 上运行的,它是在 Visual Studio 中运行的测试项目。我已经调整了提供广泛权限的私钥的权限 - 我将尝试在 IIS 上运行它。使用另一个试用证书(不需要 CSR)可以使用与上面完全相同的代码。我正在尝试了解除了在签名期间指定试用证书和/或我的设置是否存在问题之外,我是否需要执行任何其他操作。
  • 我问的是问题 1 和 2,因为您的应用程序似乎是一个 Web 应用程序,并且您正在 CurrentUser 存储中查找特定于您的用户帐户的签名证书,并且在IIS,除非应用程序池在您的帐户下运行 - 但这似乎不是您当前的问题。如果我正确理解您的评论,您已确认您的代码可以与来自同一商店的其他证书一起使用,这很可能表明您的设置存在问题。

标签: c# pdf itextsharp hsm


【解决方案1】:

您可以尝试编译并运行以下示例应用程序,该应用程序使用您从 UI 中选择的证书(和私钥)创建 CMS 签名:

using System;
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            X509Store certStore = null;
            X509Certificate2 signingCertificate = null;

            // Select signing certificate
            try
            {
                certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
                certStore.Open(OpenFlags.ReadOnly);

                X509Certificate2Collection certCollection = X509Certificate2UI.SelectFromCollection(certStore.Certificates, null, null, X509SelectionFlag.SingleSelection);
                if (certCollection == null || certCollection.Count < 1)
                    throw new Exception("No certificate selected");

                signingCertificate = certCollection[0];
                if (!signingCertificate.HasPrivateKey)
                    throw new Exception("Selected certificate is not associated with a private key");
            }
            finally
            {
                if (certStore != null)
                    certStore.Close();
            }

            // Create CMS signature with selected certificate
            byte[] dataToSign = Encoding.UTF8.GetBytes("Hello world");
            ContentInfo contentInfo = new ContentInfo(dataToSign);
            CmsSigner cmsSigner = new CmsSigner(signingCertificate);
            SignedCms signedCms = new SignedCms(contentInfo, false);
            signedCms.ComputeSignature(cmsSigner);
            byte[] signature = signedCms.Encode();

            // Parse and verify CMS signature (without certification path checking)
            SignedCms signedCms2 = new SignedCms();
            signedCms2.Decode(signature);
            signedCms2.CheckSignature(true);
        }
    }
}

如果此应用程序无法创建签名,则很可能是您的 HSM 设置存在问题(例如,证书可能与私钥错误配对)。

【讨论】:

  • 未处理的异常:System.Security.Cryptography.CryptographicException:未定义密钥集。在 System.Security.Cryptography.Pkcs.PkcsUtils.CreateSignerEncodeInfo(CmsSigner 签名者,布尔静默) 在 System.Security.Cryptography.Pkcs.SignedCms.Sign(CmsSigner 签名者,布尔静默) 在 System.Security.Cryptography.Pkcs.SignedCms.ComputeSignature (CmsSigner 签名者,布尔静默)在 System.Security.Cryptography.Pkcs.SignedCms.ComputeSignature(CmsSigner signer) 在 ConsoleApplication.Program.Main(String[] args) 在 G:\xyz - 控制台
  • App\ConsoleApplication1\ConsoleApplication1\Program.cs:line 40 感谢@jaric 提供的代码。我运行了上面的代码,得到了以下信息:我以安装证书的同一用户身份运行控制台应用程序。提供商说安装没有问题。
  • @user1024416 IMO 这证实了您的问题与 iText 无关,因为您的证书似乎在您的机器上通常无法使用。我相信您最好的办法是返回您在之前评论中提到的安装指南并重新设置 HSM。
猜你喜欢
  • 2018-12-02
  • 1970-01-01
  • 2018-02-24
  • 1970-01-01
  • 2019-10-10
  • 1970-01-01
  • 2016-01-21
  • 1970-01-01
  • 2015-10-14
相关资源
最近更新 更多