简体   繁体   中英

Signing PDFs with iTextSharp Luna HSM - Hello world

I'm trying to sign a PDF with a Luna HSM and have been given the following code:

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

            }
        }
    }
}

I'm then referencing a certificate that I have been issued and it appears to be installed correctly and has a corresponding private key which I'm able to view with certmgr.msc . I'm referencing it by it's thumbprint.

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

I get the following error:

Server Error in '/iText - HSM' Application. The keyset is not defined.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Security.Cryptography.CryptographicException: The keyset is not defined.

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:     

I would really appreciate some guidance on what I should be doing ie am I using the correct certificate?

Many thanks in advance

You can try to compile and run following sample application which creates CMS signature with the certificate (and private key) you select from the UI:

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

If this application fails to create a signature then most likely there is a problem with your HSM setup (for example the certificate may be incorrectly paired with the private key).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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