6

多年来,我一直在尝试寻找如何通过任何方式从文件中导入 ECC 密钥。我尝试从 Windows 证书存储、.p12 文件和 PKCS#8 OpenSSL 密钥文件访问 ECC 证书,但均未成功。

我尝试过的许多事情之一是:

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);

但是没有给出描述性错误消息,只有最后一行有invalid parameters或者在上面的代码的情况下An error occurred during encode or decode operation.

我正在使用来自 MSDN 的示例程序进行 ECDH,并将其更改为使用 AES 的 GCM 模式。在我尝试使用预生成的 ECC 密钥而不是 Microsoft 示例在运行时默认创建的密钥之前,所有这些都可以正常工作。我随机尝试了所有的CngKeyBlobFormats 但老实说,我不能很好地调试它,因为我不知道这些特定格式在原始数据中是什么样子的。

我的密钥采用以下格式,但我愿意使用任何可行的格式(.p12、Microsoft Store、PKCS#8 等)

密钥文件

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

资源

MSDN API 和示例:ECDiffieHellmanCng 类

MSDN API:CngKey 类

MSDN 博客:AES GCM 模式

OpenSSL - 创建 ECC 密钥

4

2 回答 2

2
  1. 使用 OpenSSL 生成 PEM 格式的 ECC 密钥:
& openssl ecparam -name "secp521r1" -genkey -param_enc explicit -out ".\private.key"

该文件的内容是:

-----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 我发布了一个私钥 - 这是一个未使用的生成的 :-)

该文件包含 SEC.1 格式的密钥,Cng 无法导入该密钥。所以我们将其转换为 PKCS#8:

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

这是 PKCS#8 内容:

-----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-----

不读取 PKCS#8 并导入密钥:

$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
于 2019-09-12T08:23:56.623 回答
0

Although this may not be the only issue, you cannot simply ASCII encode a PEM file and then act as it is a PKCS#8 encoded blob. PKCS#8 is specified in ASN.1, which is normally BER/DER encoded. PEM base 64 encodes this binary encoding and then puts a header and footer around the base 64 to indicate the type of data that was encoded.

Note that the encoded parameters may have to be skipped. Hopefully these parameters are present in the encoding of the private key.

于 2013-06-18T00:48:08.657 回答