从Windows证书库中导入基于ECC的证书到CngKey中

问题描述:

如何从基于ECC的X509Certificate2的公钥/私钥中获取与ECDsaCngECDiffieHellmanCng一起使用的CngKey从Windows证书库中导入基于ECC的证书到CngKey中

我目前使用RSA 2048位密钥对来签署/加密的东西。我这样做是通过从X509Store中抽取证书并使用标记为不可导出的私钥来安全存储的。我想将当前的实现转换为使用ECDSA和ECDH,以便我可以使用较小的密钥大小来获得同等的安全性。

使用OpenSSL的我已经成功地产生ECC证书:

  1. openssl ecparam -out private.pem -name prime256v1 -genkey
  2. openssl req -new -key private.pem -x509 -nodes -days 365 -out public.cer
  3. openssl pkcs12 -export -in public.cer -inkey private.pem -out export.pfx

我已经成功地安装了上述生成的证书到证书存储。我可以通过指纹检索它们,但私钥和公钥的加密提供程序会抛出“算法不受支持”的例外。相反,我知道我应该使用ECDsaCngECDiffieHellmanCng进行签名/加密。但这些交易在CngKey的。

Bouncy Castle不是一个选项,因为它需要私钥是可导出的。

CLR Security将通过GetCngPrivateKey返回一个CngKey对,但它不能与ECDsa一起使用,因为CLRSecurity返回的密钥是ECDH密钥。此外,CLR安全并没有给我一种方法来获取X509Certificate2的公钥以进行签名验证(我甚至没有或者不需要签名者的私钥)。

任何想法?我在我的智慧结束...任何帮助将很多赞赏。

您需要从证书的公钥创建CngKey:

certificate.PublicKey.EncodedKeyValue.RawData

的CngKey包含额外的8个字节,前4个字节用于对于所用曲线的名称(ECS1,ECS3或ECS5),最后4个是包含关键字的长度。填充(32,48或66)。

删除证书中公钥的第一个字节(因为ECDSA公钥始终为0x04)。因此,例如对于使用P-256曲线和SHA-256散列算法的ECDSA,您将获得长度为65个字节的公钥。丢弃第一个字节,留下64个字节,然后前缀4个字节用于曲线,4个字节用于密钥长度,即(编码。ASCII)

69(E)

67(C)

83(S)

49(1)

32(密钥长度)

现在你有公钥(72个字节)来创建CngKey从:

变种cngKey = CngKey.Import([字节数组],CngKeyBlobFormat.EccPublicBlob) ;

var ecdsaCng = new ECDsaCng(cngKey);

你可以验证签名:

回报ecdsaCng.VerifyData(encodedBytes,签字);

+1

但是,如果密钥不是基于RSA/DSA,那么'certificate.PublicKey'会引发问题吗? – EricLaw