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.