title: Import an OpenSSL ECDSA PEM private key and sign it
body: <p>To generate a private and public key with OpenSSL I have run</p>
  <pre class="lang-none prettyprint-override"><code>openssl ecparam -genkey -name secp256k1 -out private-key.pem
  openssl ec -in private-key.pem -out public-key.pem -pubout
  </code></pre>
  <p>I upload the public key to the remote server. Then import the <code>private-key.pem</code> to a .Net Framework (it has to be .Net Framework) C# service to use it to sign an API payload:</p>
  <pre><code>public string LoadFromCng(byte[] request, string privateKeyFile)
  {
      CngKey cng = CngKey.Open(privateKeyFile);
  
      // Sign the request body with the private key.
      ECDsaCng dsa = new ECDsaCng(cng);
      byte[] signedRequest = dsa.SignData(request, HashAlgorithmName.SHA256);
      return Convert.ToBase64String(signedRequest);
  }
  </code></pre>
  <p>With <code>privateKeyFile = private-key.pem</code> the above code gives <code>Keyset does not exist</code></p>
  <p>If I use <code>mkcert</code> and run  <code>mkcert -ecdsa -pkcs12 private-key.pem</code> it generates a PKCS#12 key called <code>private-key.pem.p12</code> and then:</p>
  <pre><code>public string LoadFromX509(byte[] request, string privateKeyFile)
  {
      var cert = new X509Certificate2(privateKeyFile, &quot;changeit&quot;);
      var key = cert.GetECDsaPrivateKey();
      byte[] signedRequest = key.SignData(request, HashAlgorithmName.SHA256);
      return Convert.ToBase64String(signedRequest);
  }
  </code></pre>
  <p>With <code>privateKeyFile = private-key.pem.p12</code> the above code appears to sign the request, but the API response is <code>The remote server returned an error: (400) Bad Request</code> which means the API provider can't decode the payload from the <code>public key</code>.</p>
  <p>I get the same 400 error when going through the <a href="https://www.scottbrady91.com/OpenSSL/Creating-Elliptical-Curve-Keys-using-OpenSSL" rel="nofollow noreferrer">cheat sheet here</a> and creating an X509 pfx certificate.</p>
  <pre class="lang-none prettyprint-override"><code>openssl req -new -x509 -key private-key.pem -out cert.pem -days 360
  openssl pkcs12 -export -inkey private-key.pem -in cert.pem -out cert.pfx
  </code></pre>
  <p>The method above appears to sign the payload but the provider responds with a 400.</p>
  <p>The suggestions <a href="https://stackoverflow.com/questions/56740429/how-to-compute-the-ecdsa-signature-using-a-p-256-key-in-a-pem-file-using-c-net?noredirect=1&amp;lq=1">here</a> and <a href="https://stackoverflow.com/questions/43160232/how-do-i-load-an-openssl-ecdsa-key-into-c">here</a> and <a href="https://stackoverflow.com/questions/13754685/how-do-i-use-a-private-key-in-c-cannot-find-the-requested-object">here</a> and <a href="https://stackoverflow.com/questions/18462064/associate-a-private-key-with-the-x509certificate2-class-in-net?noredirect=1&amp;lq=1">here</a> and others have not worked.</p>
  <p>I can't use Net Core or NET 5 so <a href="https://stackoverflow.com/questions/64933396/how-to-load-private-ecdsa-key-es256-in-c">this</a> doesn't work either. The <code>ImportPkcs8PrivateKey</code> method is not available in Net Framework.</p>
  <p>If I try and use Bouncy Castle per <a href="https://stackoverflow.com/questions/11346200/reading-pem-rsa-public-key-only-using-bouncy-castle">here</a> I get <code>Unable to cast object of type 'Org.BouncyCastle.Crypto.Parameters.ECPrivateKeyParameters' to type 'Org.BouncyCastle.Crypto.Parameters.RsaPrivateCrtKeyParameters'</code></p>