将基于ECC的证书从Windows证书存储区导入CngKey

时间:2014-03-31 13:07:32

标签: .net security x509certificate2 ecdsa cng

如何将基于ECC的X509Certificate2中的公钥/私钥转换为CngKey,以便与ECDsaCng和{{1}一起使用}}?

我目前正在使用RSA 2048位密钥对来签名/加密内容。我是通过从安全存储的ECDiffieHellmanCng中提取证书并使用标记为不可导出的私钥来实现此目的的。我想将当前实现转换为使用ECDSA和ECDH,以便我可以使用较小的密钥大小来获得同等的安全性。

我已经使用openssl成功生成了ECC证书:

  1. X509Store
  2. openssl ecparam -out private.pem -name prime256v1 -genkey
  3. openssl req -new -key private.pem -x509 -nodes -days 365 -out public.cer
  4. 我已成功将上述生成的证书安装到证书库中。我可以通过指纹检索它们,但私钥和公钥的加密提供程序抛出"算法不受支持"例外。相反,我理解我应该使用openssl pkcs12 -export -in public.cer -inkey private.pem -out export.pfxECDsaCng来签名/加密。但这些是ECDiffieHellmanCng的交易。

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

    CLR Security会通过CngKey返回CngKey对,但不能与ECDsa一起使用,因为CLRSecurity返回的密钥是ECDH密钥。此外,CLR安全无法为我提供从GetCngPrivateKey获取签名验证的公钥的方法(我甚至不需要签名者的私钥)。

    有什么想法吗?我的智慧结束了......任何帮助都会得到很多赞赏。

1 个答案:

答案 0 :(得分:6)

您需要从证书的公钥创建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个字节用于密钥长度,即(Encoding.ASCII)

  

69(E)

     

67(C)

     

83(S)

     

49(1)

     

32(密钥长度)

     

0

     

0

     

0

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

  

var cngKey = CngKey.Import([byte array],CngKeyBlobFormat.EccPublicBlob);

     

var ecdsaCng = new ECDsaCng(cngKey);

您可以验证签名:

  

返回ecdsaCng.VerifyData(encodedBytes,signature);