【问题标题】:CNG Import ECC Pub/Priv Keyfrom fileCNG 从文件导入 ECC Pub/Priv Key
【发布时间】:2013-05-09 07:50:55
【问题描述】:

多年来,我一直在尝试寻找如何通过任何方式从文件中导入 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 的 sample program 用于 ECDH 和 altered it 使用 AES 的 GCM 模式。在我尝试使用预先生成的 ECC 密钥而不是 Microsoft 示例在运行时默认创建的密钥之前,所有这些都可以正常工作。我随机尝试了所有CngKeyBlobFormats,但老实说,我无法很好地调试它,因为我不知道这些特定格式在原始数据中是什么样的。

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

key.pem

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

资源

MSDN API and Example: ECDiffieHellmanCng Class

MSDN API: CngKey Class

MSDN Blogs: AES GCM Mode

OpenSSL - Creating ECC keys

【问题讨论】:

    标签: c# cryptography elliptic-curve cng aes-gcm


    【解决方案1】:
    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
    

    【讨论】:

      【解决方案2】:

      虽然这可能不是唯一的问题,但您不能简单地对 PEM 文件进行 ASCII 编码,然后将其视为 PKCS#8 编码的 blob。 PKCS#8 在 ASN.1 中指定,通常为 BER/DER 编码。 PEM base 64 对这种二进制编码进行编码,然后在 base 64 周围放置页眉和页脚,以指示编码的数据类型。

      请注意,可能必须跳过编码参数。希望这些参数存在于私钥的编码中。

      【讨论】:

      • 很抱歉添加了迟到的内容,让 CNG 以这种方式导入密钥可能仍然非常棘手 - 如果它不起作用,您可能需要解码 PEM 格式(以及其中的关键部分PKCS#8 格式)自己。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-18
      • 1970-01-01
      • 1970-01-01
      • 2022-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多