How to convert ECDsa private key to AsymmetricKeyParameter type?

I use the below code to convert ECDsa to AsymmetricKeyParameter private key type.

X509Certificate2 x509Certificate2 = new X509Certificate2(KeyStore, pin, X509KeyStorageFlags.Exportable);  AsymmetricKeyParameter ecdsaprivKey =  x509Certificate2.GetECDsaPrivateKey(); // Error 

I got an error to convert the ecdsa private key, how could I convert that?

Add Comment
1 Answer(s)

You need to manually convert ECDsa private key parameters from .NET to BouncyCastle. I suppose that you use named curves, it is unlikely that the certificate has explicit curve parameters. If yes, then the only thing you need to bring over to BouncyCastle is a private key D parameter + OID of the curve:

using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates;  namespace EcConverter {     class Program     {         static void Main(string[] args)         {             var dotNetCertificate = new X509Certificate2("mycert.pfx", "mypassword", X509KeyStorageFlags.Exportable);             var dotNetPrivateKey = (ECDsaCng)dotNetCertificate.GetECDsaPrivateKey();             var dotNetPrivateKeyExportable = UpdateExportPolicies(dotNetPrivateKey);             var dotNetECDsaParameters = dotNetPrivateKeyExportable.ExportParameters(true);             var oid = "1.2.840.10045.3.1.7"; // nistP256Oid             var bouncyCastleD = new BigInteger(dotNetECDsaParameters.D);             var bouncyCastlePrivateKey = new ECPrivateKeyParameters("ECDSA", bouncyCastleD, new DerObjectIdentifier(oid));         }     } } 

There are a few missing pieces in this code:

First is UpdateExportPolicies(). I don’t know if you have your private key exportable or not, but it is possible that the key may not have the right export policies that would allow it to export private key parameters. If it’s true, then follow the instructions from this question on how to re-import the private key from PKCS8 blob and fix export policies (you need to have AllowPlaintextExport in dotNetPrivateKey.Key.ExportPolicy). If you have it, just skip this step.

Second is OID. You can access OID with dotNetECDsaParameters.Curve.Oid, however it may not have an actual OID code, but rather a friendly name. You can either hardcode the curve OID, or analyze the friendly name and translate it to the correct code. I have specified the most commonly used curve nistP256.

Third is a BER format that Bouncy Castle uses rather than DER to store D parameter. In most cases the code will work, but there may be issues if the private key byte array is shorter than expected and needs to be truncated. BER encoding requires the minimum number of bytes to be used and inserting a 0 byte in front. So the actual code will look something like this:

var bouncyCastleD = new BigInteger(ConvertToBer(dotNetECDsaParameters.D)); ... private byte[] ConvertToBer(byte[] derByteArray) {     // trim all zeroes in the beginning of a given array     // add one zero in front     // return the result } 
Add Comment

Your Answer

By posting your answer, you agree to the privacy policy and terms of service.