BouncyCastle create AsymmetricCipherKeyPair from existing keys? - c#

I have two AssymetricAlgorithm RSA keys that I have pulled out of a certificate that was in my keystore. One is the Public Key and the other the Private. Is there a way of getting this keypair into a BouncyCastle AsymmetricCipherKeyPair? BouncyCastle's AsymmetricCipherKeyPair expects a public and private AsymmetricKeyParameter however I have no way of getting my Private key without it being an instance of AssymetricAlgorithm.

The answer to this lies here:
Get Private Key from BouncyCastle X509 Certificate? C#

I think this will help if key is marked as exportable
RSACryptoServiceProvider key = (RSACryptoServiceProvider)X509Certificate2object.PrivateKey;
RSAParameters rsaparam = key.ExportParameters(true);
AsymmetricCipherKeyPair keypair = DotNetUtilities.GetRsaKeyPair(rsaparam);

Related

Import BouncyCastle X509Certificate + Private Key (RSA) into Windows Certificate Store

I've tried about everything to import a BouncyCastle-based X509Certificate instance with the associated private key (RsaPrivateCrtKeyParameters) via a .NET X509Certificate2 + an RSACryptoServiceProvider instances and saved it into a certificate store (.NET's X509Store, My/CurrentUser).
In the Certificate Store MMC snapin, it seems like there is a private key associated with the certificate, and I've verified that a new key container is created in the appropriate place on disk, but when I try to export the certificate, I get the dreaded "Note: The associated private key cannot be found. Only the certificate can be exported" message.
If I run certutil -user -repairstore my THUMBPRINT, I get the following error:
ERROR: Certificate public key does NOT match stored keyset
From the other information it spits out, I can clearly see that the public keys differ, and that the Algorithm Parameters equals "05 00" on the Certificate Public Key, but not on the Container Public Key.
In fact, I was not aware that there was a concept of a container public key, so I'm just very confused now. Does anyone have some working code for doing this?
I found the solution in Cabadam's answer here:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/ad01b2eb-1890-431a-86ae-e5da0e02b5b0/cryptographicexception-key-does-not-exist-when-attempting-to-connect-to-remote-service
RSACryptoServiceProvider tempRcsp = (RSACryptoServiceProvider)DotNetUtilities.ToRSA((RsaPrivateCrtKeyParameters)keyPair.Private);
RSACryptoServiceProvider rcsp = new RSACryptoServiceProvider(new CspParameters(1, "Microsoft Strong Cryptographic Provider", new Guid().ToString(), new CryptoKeySecurity(), null));
rcsp.ImportCspBlob(tempRcsp.ExportCspBlob(true));
dotnetCertificate2.PrivateKey = rcsp;
// Save the certificate to the X509Store

Digital signature using bouncy castle and certificate private key

I am developing a feature to digital sign some content. I have valid certificate with a private key. How to digital sign using the private key and bouncy castle?
I tried the following but want some right way to achieve the same using bouncy castle:
X509Certificate2 signingCert =
CryptoHelper.FindCertificate("21A6107EC254457AAF3D4D6FD286FB79");
var rsaObj = (RSACryptoServiceProvider)signingCert.PrivateKey;
_privateKey = rsaObj.ExportParameters(true);
Thanks!
I donĀ“t know exactly what you need based on your code, but there X509 namespace/code is at
bcgit/bc-csharp - X509 and there is an utility class for conversion between System.Security.Cryptography and BouncyCastle
bcgit/bc-csharp - DotNetUtilities.cs
BouncyCastle got lots of test (and examples). Have a look at bcgit/bc-csharp - TestCertificateGen.cs too. Maybe this helps you.
EDIT: In general it should go something like this
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
// Your loaded certificate
X509Certificate cert = null;
// Your loaded RSA key
AsymmetricKeyParameter privateKey = null;
AsymmetricKeyParameter publicKey = cert.GetPublicKey();
ISigner signer = SignerUtilities.GetSigner(cert.SigAlgName);
// Init for signing, you pass in the private key
signer.Init(true, privateKey);
// Init for verification, you pass in the public key
signer.Init(false, publicKey);
Greetings

How to use GnuPG (Libgcrypt) generated keys with RSACryptoServiceProvider?

Is it possible to use PGP keys in .NET's RSA?
I tried this code, without success.
X509Certificate2 certificate = new X509Certificate2();
certificate.Import("C:\\All Public Keys.asc");
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)certificate.PrivateKey;
How to load this key?

How can I add a private key to X509Certificate2 after I have already added the public key?

My steps are:
Create X509Certificate2 with public key:
X509Certificate2 clientCertificate = new X509Certificate2("public key certificate blob as byte[]");
How do I want to load the private key blob to clientCertificate?
It looks like you can not import RSA private key with just .net framework tools.
Check out this thread How to read a PEM RSA private key from .NET.
Just in case anyone like me and up looking at this old post when searching for how to generate X509Certificate2 from pem fil/private key:
The .Net 5.0 framework has a very simplified approach to this:
var certPem = File.ReadAllText("cert.pem");
var eccPem = File.ReadAllText("ecc.pem");
var cert = X509Certificate2.CreateFromPem(certPem, eccPem);
(source: https://www.scottbrady91.com/C-Sharp/PEM-Loading-in-dotnet-core-and-dotnet)
Also see: How to import PKCS#8 RSA privateKey (created by OpenSSL) in C#
It includes a link to Mono's source code which can read PKCS#8 / PEM files and return an RSA instance from it.

How do you generate an x509Certificate based solely on a public key in RSA format?

I have an RSA public key in an XML format. I need to take this key and create an x.509 Certificate using that public key. I do not have access to the private key to complete the key pair. All examples that I have found involve either generating the key pair or having access to both the public and private keys.
Below is a small snippet from a test routine I have been working on to accomplish this.
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
provider.FromXmlString("<RSAKeyValue><Modulus>puEVvRbrLAz.......c1W5j/vqJSUrXo16k=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>");
Org.BouncyCastle.Crypto.Parameters.RsaKeyParameters key = Org.BouncyCastle.Security.DotNetUtilities.GetRsaPublicKey(provider);
//<!*** Do some code to take RsaKeyParameters and create an x.509 Certificate ***>
var fOut = new System.IO.StreamWriter(#"C:\certificate.pem", false);
var pw = new Org.BouncyCastle.OpenSsl.PemWriter(fOut);
pw.WriteObject(key);
Just to clarify the issue of impossibility of generating a certificate using a public key only.
AFAIK, certificate must be signed. And it must be done with a private key - that's why you need one for generating a certificate. If certificate is signed with the paired private key of the open key you are going to issue a certificate for, than it is a self-signed certificate. Otherwise you need a private key of so called Certificate Authority for signing.

Categories