I'm trying to generate (self-signed) certificate with private key using ECDSA. The goals is to get "the same" (pkcs12) certificate as when using openssl:
openssl ecparam -genkey -name secp256r1 -out mykey.key
openssl req -new -key mykey.key -out myreq.csr
openssl req -x509 -days 7 -key mykey.key -in myreq.csr -out mycert.crt
openssl pkcs12 -export -out mycert.pfx -inkey mykey.key -in mycert.crt
I already use BouncyCastle to help me with creating RSA-based certificate(s), so next steps more or less follow the way I use to create RSA certs.
(note that BC prefix is used for classes from BouncyCastle, MS for .NET classes)
1 generate key pair: private and public keys
BC.IAsymmetricCipherKeyPairGenerator bcKpGen = BC.GeneratorUtilities.GetKeyPairGenerator("ECDSA");
bcKpGen.Init(new BC.ECKeyGenerationParameters(BC.SecObjectIdentifiers.SecP256r1, new BC.SecureRandom()));
BC.AsymmetricCipherKeyPair bcSubjKeys = bcKpGen.GenerateKeyPair();
2 use private key to sign public key with some additional data (subject, validity period etc)
BC.X509V3CertificateGenerator bcXgen = new BC.X509V3CertificateGenerator();
// .. set subject, validity period etc
bcXgen.SetPublicKey(bcSubjKeys.Public);
BC.ISignatureFactory bcSigFac = new BC.Asn1SignatureFactory("SHA256WITHECDSA", bcSubjKeys.Private);
BC.X509Certificate bcCert = bcXgen.Generate(bcSigFac);
3 "join" private key from step1 and certificate from step2 to get certificate with private key.
If I'm ok with certificate without private key, I could do something like:
MS.X509Certificate mcCert = new MS.X509Certificate2(bcCert.GetEncoded(), null);
and I'm done.
The issue(s) come when trying to set private-key:
msCert.PrivateKey = ConvertBouncyToNetSomehow(bcSubjKeys.Private)
(note that typeof msCert.PrivateKey is MS.AsymmetricAlgorithm and the type of bcSubjKeys.Private is BC.ECPrivateKeyParameters)
It seems that suitable way is using MS.ECDsaCng class (which inherits from MS.AsymmetricAlgorithm), but:
1 The only way I found to convert BC.ECPrivateKeyParameters to MS.CngKey (required by MS.ECDsaCng) is via pkcs8 format:
BC.PrivateKeyInfo bcPKInfo = BC.PrivateKeyInfoFactory.CreatePrivateKeyInfo(bcSubjKeys.Private);
byte[] pkArr = bcPKInfo.GetDerEncoded();
MS.CngKey msPKCng = MS.CngKey.Import(pkArr, MS.CngKeyBlobFormat.Pkcs8PrivateBlob);
but using this approach some information is lost because value of msPKCng.AlgorithmGroup is "ECDH" while bcSubjKeys.Private.AlgorithmNamesays "ECDSA". Also ECDH-key cannot be used with MS.ECDsaCng.
Nevertheless.. I could continue with MS.ECDiffieHellmanCng instead of requested MS.ECDsaCng if..
2 implementation of MS.X509Certificate2.set_PrivateKey requires the object implements interface MS.ICspAsymmetricAlgorithm. But neither one of them (ECDsaCng, ECDiffieHellmanCng) implement it.
At this point it seems different approach must be used (because of MS.ICspAsymmetricAlgorithm condition), e.g. export certificate and private key to pkcs file and use X509Certificate2.Import(..).
Any hint? Regards