2017-04-01 28 views
2

我需要将OpenSSL私钥加载到基于C#的应用程序中。如何将OpenSSL ECDSA密钥加载到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正确的方法是什么?


EDIT

基64编码内的关键粘附到下面的格式:

ECPrivateKey ::= SEQUENCE { 
    version  INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), 
    privateKey  OCTET STRING, 
    parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, 
    publicKey [1] BIT STRING OPTIONAL 
} 

使用secp256r1曲线和在未压缩格式点的公共密钥。

+1

您可以尝试使用“Pkcs8PrivateBlob”格式吗?嗯,相信这会起作用,请让我回答,如果是这样的话。 –

+0

@MaartenBodewes看起来像这样做! – LamonteCristo

回答

3

使用RFC 5915: Elliptic Curve Private Key Structure中描述的格式对您的密钥PEM/ASCII装甲(页眉,页脚和底部64)进行编码。这是由高效密码组(SECG)首次指定的,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中携带(可选)公钥值。

所以解码器识别这种类型并返回EC私钥。


EccPrivateBlob您正在使用需要Microsoft specific structure。另见我的问题here。它不适用于上述结构。

+1

我做了一个更改,但没有更新问题,我运行了第二个OpenSSL命令,然后导入了该私钥输出。 'openssl pkcs8 -topk8 -nocrypt -in eckey.pem -out ec2.pem'。不知道这是否会改变答案/ b/c ASN1可能与您首次观察到的不同。 – LamonteCristo

+0

done ........... – LamonteCristo

+0

是PKCS8(十六进制以上)ASN1格式?我试图使用https://lapo.it/asn1js/解码它,但它似乎没有工作... – LamonteCristo