I need to import ECC certificates into Windows Key Stores in C#. As the first step, I am using BouncyCastle to generate an EC key pair, create an X509 certificate with the public key, and sign it with the ECDSA and private key, i.e.,:
var ecKeyPairGenerator = new ECKeyPairGenerator("ECDSA");
ECKeyGenerationParameters ecKeyGenParams =
new ECKeyGenerationParameters(SecObjectIdentifiers.SecP384r1, new SecureRandom());
ecKeyPairGenerator.Init(ecKeyGenParams);
AsymmetricCipherKeyPair pair = ecKeyPairGenerator.GenerateKeyPair();
PrivateKeyInfo privKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(pair.Private);
SubjectPublicKeyInfo pubKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pair.Public);
X509V3CertificateGenerator bcX509Gen = new X509V3CertificateGenerator();
// set cert fields
...
bcX509Gen.SetPublicKey(pair.Public);
Asn1SignatureFactory bcSigFactory =
new Asn1SignatureFactory(X9ObjectIdentifiers.ECDsaWithSha384.Id, pair.Private);
X509Certificate bcCert = bcX509Gen.Generate(bcSigFactory);
Then, I create an X509Certificate2 with the certificate created above, i.e.,:
SystemX509.X509Certificate2 msCert2 =
new SystemX509.X509Certificate2(bcCert.GetEncoded(), (string)null);
However, an exception is raised in creating the X509Certificate2:
'msCert2.PublicKey.Key' threw an exception of type 'System.NotSupportedException'
"The certificate key algorithm is not supported."
Using BC's DotNetUtilities.ToX509Certificate() results in the same exception.
I'm aware that the support for ECC certificates on Windows / .NET may not be complete, but my searches on the web seem to suggest that this should be possible? Any ideas what I'm doing wrong?
FYI, I'm using VS Community 2017, and my project has the target of .NET Framework 4.6.2.
Thanks!
PublicKey.Key
is unofficially deprecated (along with PrivateKey
). It doesn't support ECC, and doesn't produce an RSA key that is capable of doing OAEP-SHA-2 encryption or DSA key capable of doing FIPS 186-3 DSA.
Instead you want to use the extension methods which don't require casting:
// GetECDsaPublicKey returns a unique object every call,
// so you're responsible for Disposing it (lest it end up on the Finalizer queue)
using (ECDsa ecdsa = msCert2.GetECDsaPublicKey())
{
// do stuff with the public key object
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With