Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CNG Import ECC Pub/Priv Keyfrom file

I've been trying to find how to import an ECC key from a file by ANY MEANS for ages. I have tried accessing an ECC cert from the Windows certificate store, from a .p12 file, and from a PKCS#8 OpenSSL key file with no success.

Just one of the many things I have tried is:

StreamReader fs = new StreamReader("key.pem");
String key = fs.ReadToEnd();
byte[] tempkey = System.Text.Encoding.ASCII.GetBytes(key);
CngKey cngKey = CngKey.Import(tempkey, CngKeyBlobFormat.Pkcs8PrivateBlob);

But no discriptive error messages are given, only that the last line either has invalid parameters or in the case of the code above An error occurred during encode or decode operation.

I am using the sample program from MSDN for ECDH and altered it to use the GCM mode of AES. All of this works fine until I try and use pre-generated ECC keys instead of the ones created by default at runtime for the Microsoft example. I have randomly tried all of the CngKeyBlobFormats but to be honest, I can't debug it very well because I don't know what those specific formats look like in raw data.

My key is in the following format however I am willing to use any format that will work (.p12, Microsoft Store, PKCS#8, etc.)

key.pem

-----BEGIN EC PARAMETERS-----
##############################
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
##############################
-----END EC PRIVATE KEY-----

Resources

MSDN API and Example: ECDiffieHellmanCng Class

MSDN API: CngKey Class

MSDN Blogs: AES GCM Mode

OpenSSL - Creating ECC keys

like image 232
Jim Avatar asked May 14 '13 21:05

Jim


1 Answers

  1. Generate an ECC key in PEM format using OpenSSL:
& openssl ecparam -name "secp521r1" -genkey -param_enc explicit -out ".\private.key"

The contents of the file is:

-----BEGIN EC PARAMETERS-----
MIIBwwIBATBNBgcqhkjOPQEBAkIB////////////////////////////////////
//////////////////////////////////////////////////8wgZ8EQgH/////
////////////////////////////////////////////////////////////////
/////////////////ARCAFGVPrlhjhyaH5KaIaC2hUDuotpyW5mzFfO4tImRjvEJ
4VYZOVHsfpN7FlLAvTuxvwc1c9+IPSw08e9FH9RrUD8AAxUA0J6IACkcuFOWzGcX
OTKEqqDaZLoEgYUEAMaFjga3BATpzZ4+y2YjlbRCnGSBOQU/tSH4KK9ga009uqFL
Xnfv51ko/h3BJ6L/qN4zSLPBhWpCm/l+fjHC5b1mARg5KWp4mjvABFyKX7QsfRvZ
mPVESVebRGgXr70XJz5mLJfucple9CZAxVC5AT+tB2E1PHCGonLCQIi+lHaf0WZQ
AkIB///////////////////////////////////////////6UYaHg78vlmt/zAFI
9wml0Du1ybiJnEeuu2+3HpE4ZAkCAQE=
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MIICngIBAQRCABEwHYVa214LUODzm4BXWkBFSTBDU/N/nNwTB/mAP1Khpn0vd0QH
b/8BrfMbUYzzWXtXsvRvxPzKB2Sc6s7JC8CfoIIBxzCCAcMCAQEwTQYHKoZIzj0B
AQJCAf//////////////////////////////////////////////////////////
////////////////////////////MIGfBEIB////////////////////////////
//////////////////////////////////////////////////////////wEQgBR
lT65YY4cmh+SmiGgtoVA7qLacluZsxXzuLSJkY7xCeFWGTlR7H6TexZSwL07sb8H
NXPfiD0sNPHvRR/Ua1A/AAMVANCeiAApHLhTlsxnFzkyhKqg2mS6BIGFBADGhY4G
twQE6c2ePstmI5W0QpxkgTkFP7Uh+CivYGtNPbqhS1537+dZKP4dwSei/6jeM0iz
wYVqQpv5fn4xwuW9ZgEYOSlqeJo7wARcil+0LH0b2Zj1RElXm0RoF6+9Fyc+ZiyX
7nKZXvQmQMVQuQE/rQdhNTxwhqJywkCIvpR2n9FmUAJCAf//////////////////
////////////////////////+lGGh4O/L5Zrf8wBSPcJpdA7tcm4iZxHrrtvtx6R
OGQJAgEBoYGJA4GGAAQAIzBvnlURokMqtUyYrOJ5Kd1Mz0/7xGXkbhOR4ReIt9mt
hsL2tK3PQWj/j28IEajPRbVtxxA7McxQfayY9vUKdF8A6+qkOBCji82nKwKyu2+9
7l5FowAW05SdWRgJnqHU5ENf2h3Hje5UH1AidcpDZgTDuCV263PRKCUqUwX+LRN3
t7Y=
-----END EC PRIVATE KEY-----

Uhhhh I posted a private key - This is a generated one not used :-)

The file contains the key in SEC.1 format, which Cng cannot import. So we convert it to PKCS#8:

& openssl pkcs8 -topk8 -inform pem -in ".\private.key" -outform PEM -nocrypt -out ".\private_plain.p8"

Here is the PKCS#8 content:

-----BEGIN PRIVATE KEY-----
MIICsAIBADCCAdAGByqGSM49AgEwggHDAgEBME0GByqGSM49AQECQgH/////////
////////////////////////////////////////////////////////////////
/////////////zCBnwRCAf//////////////////////////////////////////
///////////////////////////////////////////8BEIAUZU+uWGOHJofkpoh
oLaFQO6i2nJbmbMV87i0iZGO8QnhVhk5Uex+k3sWUsC9O7G/BzVz34g9LDTx70Uf
1GtQPwADFQDQnogAKRy4U5bMZxc5MoSqoNpkugSBhQQAxoWOBrcEBOnNnj7LZiOV
tEKcZIE5BT+1Ifgor2BrTT26oUted+/nWSj+HcEnov+o3jNIs8GFakKb+X5+McLl
vWYBGDkpaniaO8AEXIpftCx9G9mY9URJV5tEaBevvRcnPmYsl+5ymV70JkDFULkB
P60HYTU8cIaicsJAiL6Udp/RZlACQgH/////////////////////////////////
//////////pRhoeDvy+Wa3/MAUj3CaXQO7XJuImcR667b7cekThkCQIBAQSB1jCB
0wIBAQRCABEwHYVa214LUODzm4BXWkBFSTBDU/N/nNwTB/mAP1Khpn0vd0QHb/8B
rfMbUYzzWXtXsvRvxPzKB2Sc6s7JC8CfoYGJA4GGAAQAIzBvnlURokMqtUyYrOJ5
Kd1Mz0/7xGXkbhOR4ReIt9mthsL2tK3PQWj/j28IEajPRbVtxxA7McxQfayY9vUK
dF8A6+qkOBCji82nKwKyu2+97l5FowAW05SdWRgJnqHU5ENf2h3Hje5UH1AidcpD
ZgTDuCV263PRKCUqUwX+LRN3t7Y=
-----END PRIVATE KEY-----

Not read the PKCS#8 and import the key:

$bytes = [Convert]::FromBase64String(
  [String]::Join(
    [String]::Empty, 
    ([IO.File]::ReadAllLines(".\private_plain.p8") `
      | Where-Object { $_.StartsWith("-") -ne $true })));

$key = [System.Security.Cryptography.CngKey]::Import(
  $bytes, 
  [System.Security.Cryptography.CngKeyBlobFormat]::Pkcs8PrivateBlob);

Write-Host $key.Algorithm
like image 62
Daniel Fisher lennybacon Avatar answered Oct 04 '22 07:10

Daniel Fisher lennybacon