如何将 OpenSSL ECDSA 密钥加载到 C# 中?
How do I load an OpenSSL ECDSA key into C#?
我需要将 OpenSSL 私钥加载到基于 C# 的应用程序中。
我用来生成密钥的命令是:
$ openssl ecparam -name prime256v1 -genkey -noout -out eckey.pem
$ openssl ec -in eckey.pem
read EC key
writing EC key
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIMiuwhV+yI0od5E5pSU6ZGuUcflskYD4urONi1g3G7EPoAoGCCqGSM49
AwEHoUQDQgAEe+C/M6u171u5CcL2SQKuFEb+OIEibjw1rx+S5LK4gNNePlDV/bqu
Ofjwc5JDqXA07shbfHNIPUn6Hum7qdiUKg==
-----END EC PRIVATE KEY-----
openssl pkcs8 -topk8 -nocrypt -in eckey.pem -out ec2.pem
cat ec2.pem
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgyK7CFX7IjSh3kTml
JTpka5Rx+WyRgPi6s42LWDcbsQ+hRANCAAR74L8zq7XvW7kJwvZJAq4URv44gSJu
PDWvH5LksriA014+UNX9uq45+PBzkkOpcDTuyFt8c0g9Sfoe6bup2JQq
-----END PRIVATE KEY-----
我正在使用的 C# 代码
string privKeyPKCS8 = @"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgyK7CFX7IjSh3kTmlJTpka5Rx+WyRgPi6s42LWDcbsQ+hRANCAAR74L8zq7XvW7kJwvZJAq4URv44gSJuPDWvH5LksriA014+UNX9uq45+PBzkkOpcDTuyFt8c0g9Sfoe6bup2JQq";
byte[] privKeyBytes8 = Convert.FromBase64String(privKeyPKCS8);//Encoding.UTF8.GetBytes(privKeyEcc);
var pubCNG = CngKey.Import(privKeyBytes, CngKeyBlobFormat.EccPrivateBlob);
将基于 EC 的密钥加载到 CngKey 的正确方法是什么?
编辑
base 64 编码中的密钥遵循以下格式:
ECPrivateKey ::= SEQUENCE {
version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
privateKey OCTET STRING,
parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
publicKey [1] BIT STRING OPTIONAL
}
使用 secp256r1 曲线和未压缩点格式的 public 密钥。
您的关键 PEM/ASCII 装甲(页眉、页脚和 base 64)使用 RFC 5915: Elliptic Curve Private Key Structure 中描述的格式进行编码。这首先由高效密码组标准 (SECG) 指定,这也是命名曲线 secp256r1 的名称来源。 Microsoft CNG 支持该曲线。
ECPrivateKey ::= SEQUENCE {
version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
privateKey OCTET STRING,
parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
publicKey [1] BIT STRING OPTIONAL
}
您首先需要使用(更新的)问题中的命令将此“原始”EC 私钥结构转换为 PKCS#8 结构:
openssl pkcs8 -topk8 -nocrypt -in eckey.pem -out ec2.pem
获得:
SEQUENCE(3 elem)
INTEGER 0 # version of PKCS#8 structure
SEQUENCE (2 elem)
OBJECT IDENTIFIER 1.2.840.10045.2.1 # it's an EC key)
OBJECT IDENTIFIER 1.2.840.10045.3.1.7 # it's secp256r1
OCTET STRING (1 elem) # the key structure
SEQUENCE (3 elem)
INTEGER 1 # version
OCTET STRING (32 byte) # private key value (removed)
[1] (1 elem)
BIT STRING (520 bit) # public key value (removed)
生成的结构并没有什么不同,您所看到的实际上与初始结构相同。除了 PKCS#8 结构有一个用于指定密钥类型的对象标识符 (OID) 和一个用于前面曲线本身的 OID,而您的密钥后面只有 OID 作为参数。两者还在 BIT STRING 中携带(可选)public 键值。
所以解码器识别这种类型和returnsEC私钥。
您使用的 EccPrivateBlob
需要 Microsoft specific structure. See also my question 。它不适用于上述结构。
我需要将 OpenSSL 私钥加载到基于 C# 的应用程序中。
我用来生成密钥的命令是:
$ openssl ecparam -name prime256v1 -genkey -noout -out eckey.pem
$ openssl ec -in eckey.pem
read EC key
writing EC key
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIMiuwhV+yI0od5E5pSU6ZGuUcflskYD4urONi1g3G7EPoAoGCCqGSM49
AwEHoUQDQgAEe+C/M6u171u5CcL2SQKuFEb+OIEibjw1rx+S5LK4gNNePlDV/bqu
Ofjwc5JDqXA07shbfHNIPUn6Hum7qdiUKg==
-----END EC PRIVATE KEY-----
openssl pkcs8 -topk8 -nocrypt -in eckey.pem -out ec2.pem
cat ec2.pem
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgyK7CFX7IjSh3kTml
JTpka5Rx+WyRgPi6s42LWDcbsQ+hRANCAAR74L8zq7XvW7kJwvZJAq4URv44gSJu
PDWvH5LksriA014+UNX9uq45+PBzkkOpcDTuyFt8c0g9Sfoe6bup2JQq
-----END PRIVATE KEY-----
我正在使用的 C# 代码
string privKeyPKCS8 = @"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgyK7CFX7IjSh3kTmlJTpka5Rx+WyRgPi6s42LWDcbsQ+hRANCAAR74L8zq7XvW7kJwvZJAq4URv44gSJuPDWvH5LksriA014+UNX9uq45+PBzkkOpcDTuyFt8c0g9Sfoe6bup2JQq";
byte[] privKeyBytes8 = Convert.FromBase64String(privKeyPKCS8);//Encoding.UTF8.GetBytes(privKeyEcc);
var pubCNG = CngKey.Import(privKeyBytes, CngKeyBlobFormat.EccPrivateBlob);
将基于 EC 的密钥加载到 CngKey 的正确方法是什么?
编辑
base 64 编码中的密钥遵循以下格式:
ECPrivateKey ::= SEQUENCE {
version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
privateKey OCTET STRING,
parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
publicKey [1] BIT STRING OPTIONAL
}
使用 secp256r1 曲线和未压缩点格式的 public 密钥。
您的关键 PEM/ASCII 装甲(页眉、页脚和 base 64)使用 RFC 5915: Elliptic Curve Private Key Structure 中描述的格式进行编码。这首先由高效密码组标准 (SECG) 指定,这也是命名曲线 secp256r1 的名称来源。 Microsoft CNG 支持该曲线。
ECPrivateKey ::= SEQUENCE {
version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
privateKey OCTET STRING,
parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
publicKey [1] BIT STRING OPTIONAL
}
您首先需要使用(更新的)问题中的命令将此“原始”EC 私钥结构转换为 PKCS#8 结构:
openssl pkcs8 -topk8 -nocrypt -in eckey.pem -out ec2.pem
获得:
SEQUENCE(3 elem)
INTEGER 0 # version of PKCS#8 structure
SEQUENCE (2 elem)
OBJECT IDENTIFIER 1.2.840.10045.2.1 # it's an EC key)
OBJECT IDENTIFIER 1.2.840.10045.3.1.7 # it's secp256r1
OCTET STRING (1 elem) # the key structure
SEQUENCE (3 elem)
INTEGER 1 # version
OCTET STRING (32 byte) # private key value (removed)
[1] (1 elem)
BIT STRING (520 bit) # public key value (removed)
生成的结构并没有什么不同,您所看到的实际上与初始结构相同。除了 PKCS#8 结构有一个用于指定密钥类型的对象标识符 (OID) 和一个用于前面曲线本身的 OID,而您的密钥后面只有 OID 作为参数。两者还在 BIT STRING 中携带(可选)public 键值。
所以解码器识别这种类型和returnsEC私钥。
您使用的 EccPrivateBlob
需要 Microsoft specific structure. See also my question