在Luna HSM上使用iTextSharp进行签名

时间:2014-06-27 11:23:20

标签: c# encryption itextsharp bouncycastle hsm

环境:

C#4.5,Windows Server 2008 R2,iTextSharp v5.5.1,由GlobalSign主办的Luna SA HSM。

问题:

每当我尝试签署PDF时,我都会遇到以下异常:

Invalid provider type specified.
   at System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer)
   at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle)
   at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair()
   at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize)
   at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()
   at iTextSharp.text.pdf.security.X509Certificate2Signature..ctor(X509Certificate2 certificate, String hashAlgorithm)

代码:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
using Org.BouncyCastle.Security;
using X509Certificate = Org.BouncyCastle.X509.X509Certificate;

namespace SignWithHsm
{
    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 src, string dest)
    {
        using (var reader = new PdfReader(src))
        {
            using (var os = new FileStream(dest, FileMode.Create))
            {
                using (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);
                }
            }
        }
     }
   }
}

已验证与HSM的连接。 Sign类的证书是我从GlobalSign获得的证书。它不是存储在HSM上的证书。

为什么我会得到例外?我错过了什么?

1 个答案:

答案 0 :(得分:0)

问题解决了。不是将证书存储在KSP中,而是将其放在CSP中。然后我们可以使用SignDetached方法。