4

I've used following commands to generate private and public ES256 keys:

Create private key: openssl ecparam -genkey -name prime256v1 -noout -out private.pem

Create public key: openssl ec -in private.pem -pubout -out public.pem

Now I got following private key:

-----BEGIN EC PRIVATE KEY----- MHcCAQEEIFkxqdXoVAGSSc55u0muepwVRr3ARWzLMO0ywW7qhEeIoAoGCCqGSM49 AwEHoUQDQgAEFXuuZeDJN9dvjCwKy40/coi3NVto97qELhiRSObbhX3mUSvxpPeK fVv3/fVCjt9CeGuwYvkQPHmRfx0EFjAI8A== -----END EC PRIVATE KEY-----

And following public key:

-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFXuuZeDJN9dvjCwKy40/coi3NVto 97qELhiRSObbhX3mUSvxpPeKfVv3/fVCjt9CeGuwYvkQPHmRfx0EFjAI8A== -----END PUBLIC KEY-----

I want to load these keys into ecdsa instance in c#. I do that with following code:

public ECDsaSecurityKey LoadPrivateKey()
    {
        byte[] privateKey = Convert.FromBase64String(PRIVATE_KEY);
        try
        {
            ECDsa? privateKeyEcDsa = ECDsa.Create();

            if (privateKeyEcDsa == null)
            {
                throw new CryptographicException(message: "Key not created");
            }

            privateKeyEcDsa.ImportPkcs8PrivateKey(source: privateKey, bytesRead: out _);

            return new ECDsaSecurityKey(privateKeyEcDsa);
        }
        catch (CryptographicException exception)
        {    
            throw;
        }
    }

And public key:

     public ECDsaSecurityKey LoadPublicKey()
        {
byte[] publicKey = Convert.FromBase64String(PUBLIC_KEY);
            try
            {
                ECDsa? publicKeyEcDsa = ECDsa.Create();

                if (publicKeyEcDsa == null)
                {
                    throw new CryptographicException(message: "Key not created");
                }

                publicKeyEcDsa.ImportSubjectPublicKeyInfo(source: publicKey, bytesRead: out _);

                return new ECDsaSecurityKey(publicKeyEcDsa);
            }
            catch (CryptographicException exception)
            {
                this._logger.LogError("Something went wrong while loading EcDsa public key: " + exception.Message);

                throw;
            }
        }

When I run unit test, thing doesn't work, throws an error: enter image description here

I am not sure why is this not working? Is the openssl command generating correct keypair type?

EDIT: On this website when I select ES256 private key is different: https://kjur.github.io/jsjws/tool_jwt.html

Example:

-----BEGIN PRIVATE KEY----- MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgEbVzfPnZPxfAyxqE ZV05laAoJAl+/6Xt2O4mOB611sOhRANCAASgFTKjwJAAU95g++/vzKWHkzAVmNMI tB5vTjZOOIwnEb70MsWZFIyUFD1P9Gwstz4+akHX7vI8BH6hHmBmfeQl -----END PRIVATE KEY-----

And my private key generated with OpenSSL add two equals in the end:

-----BEGIN EC PRIVATE KEY----- MHcCAQEEIFkxqdXoVAGSSc55u0muepwVRr3ARWzLMO0ywW7qhEeIoAoGCCqGSM49 AwEHoUQDQgAEFXuuZeDJN9dvjCwKy40/coi3NVto97qELhiRSObbhX3mUSvxpPeK fVv3/fVCjt9CeGuwYvkQPHmRfx0EFjAI8A== -----END EC PRIVATE KEY-----

So I guess I am doing something wrong with open ssl.

sensei
  • 7,044
  • 10
  • 57
  • 125

1 Answers1

3

The private key has the SEC1 format and not the PKCS#8 format, i.e. the import must be done via ImportECPrivateKey().

The public key is an X.509/SPKI key, so ImportSubjectPublicKeyInfo() is correct.

Both methods expect a DER encoded key, i.e. without header and footer and Base64 decoded body.

If this is taken into account, the code works (at least on my machine).

The methods are available in .NET Core 3.x and .NET 5.0.

Topaco
  • 40,594
  • 4
  • 35
  • 62
  • 1
    thanks, if anyone needs this in pkcs#8 format for jwt signing and verifying use this `openssl pkcs8 -topk8 -nocrypt -in ec1.pem -out ec2.pem` – sensei Nov 22 '20 at 15:07