I have been able to sign a document with a certificate that was installed on the machine with “export key” option enabled. But when I try the same thing with a non-exportable certificate, it fails to load the private key.
I am aware that X509Certificate2.PrivateKey is depricated and x509Certificate2.GetRSAPrivateKey() function should be used instead, but I don’t know how because Org.BouncyCastle.Security.DotNetUtilities.GetKeyPair() throws an error if used with GetRSAPrivateKey().
This is the verison of the code that works, only when certificate is installed as exportable:
X509Certificate2 certificate = null;
using (X509Store localMachineStore = new X509Store(StoreLocation.LocalMachine))
{
localMachineStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection wantedCertificateCollection = localMachineStore.Certificates.Find(X509FindType.FindBySerialNumber, @"123456798", true);
if(wantedCertificateCollection.Count != 1)
{
throw new Exception("Certificate not found in Store!");
}
certificate = wantedCertificateCollection[0];
}
PdfReader pdfReader = new PdfReader(reportBytes);
using (MemoryStream fout = new MemoryStream())
{
try
{
PdfStamper stamper = PdfStamper.CreateSignature(pdfReader, fout, '');
PdfSignatureAppearance signatureAppearance = stamper.SignatureAppearance;
signatureAppearance.Render = PdfSignatureAppearance.SignatureRender.NameAndDescription;
signatureAppearance.SignDate = DateTime.Now;
signatureAppearance.Acro6Layers = true;
signatureAppearance.SetVisibleSignature(new iTextSharp.text.Rectangle(380, 230, 550, 280), pdfReader.NumberOfPages, "CustomField");
AsymmetricAlgorithm privateKeyAsymAlgo = certificate.PrivateKey; // <--- THIS LINE THROWS EXCEPTION IF CERTIFICATE IS MADE NON-EXPORTABLE
Org.BouncyCastle.Crypto.AsymmetricKeyParameter asymmetricKeyParameter = Org.BouncyCastle.Security.DotNetUtilities.GetKeyPair(privateKeyAsymAlgo).Private;
Org.BouncyCastle.X509.X509Certificate chain = Org.BouncyCastle.Security.DotNetUtilities.FromX509Certificate(certificate);
signatureAppearance.SetCrypto(asymmetricKeyParameter, new[] { chain }, null, PdfSignatureAppearance.WINCER_SIGNED);
stamper.Writer.CloseStream = false;
stamper.Close();
return fout.ToArray();
}catch(Exception e)
{
throw e;
}
}
I am aware that I’m using outdated library. We are in the process of migrating the code base, but as it is a legacy system it takes time and in the meantime it needs to work as is.
Application is using .Net Framework 4.6.2