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.AlgorithmName
says "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