在.NET中加载ECC私钥

4

我有一个ECC私钥和一个证书文件,其中包含公钥。我可以获取它们的PEM或DER格式。

我可以使用以下代码将证书读入X509Certificate

var certbytes = File.ReadAllBytes("certificate.pem");
var cert = new X509Certificate2(certbytes);

但是我无法加载私钥。 我已尝试使用以下代码:

var keyContent = File.ReadAllBytes("certificate_private_key.pem");
var key = CngKey.Import(keyContent, CngKeyBlobFormat.EccPrivateBlob);

它会抛出 Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException: '在编码或解码操作期间发生错误'

我还尝试了CngKeyBlobFormat参数的其他值。导入方法也失败了。

openssl可以读取该文件,并输出以下关于该文件的信息:

openssl ec -in certificate_private_key.pem -text
read EC key
Private-Key: (256 bit)
priv:
    44:<cut>:68
pub:
    04:<cut>:13
ASN1 OID: prime256v1
NIST CURVE: P-256
writing EC key
-----BEGIN EC PRIVATE KEY-----
MHcC <cut here>
-----END EC PRIVATE KEY-----

在 .NET 或 .NET Core 中是否有内置的 API 可以实现这一功能?或者有第三方库可以实现,如何使用?


谢谢您的提示。openssl pkcs8无法理解该文件,只有openssl ec可以。我已经拥有DER和PEM格式的文件,但都无法使用。根据CngKeyBlobFormat参数,异常要么是编码或解码操作期间发生错误,要么是参数不正确。我还尝试将DER文件转换为显式EC文件,使用openssl ec -in certificate_private_key.der -inform DER -param_enc explicit -out explicit.der -outform der,并将CngKeyBlobFormat.EccFullPrivateBlob用作格式,但在导入时仍然失败。 - RasmusW
哦,那样的话它就是X9.62格式。从 -----BEGIN EC PRIVATE KEY----- 头部应该就能看出来了。X9.62私钥是PKCS#8文件中的内容。 - Maarten Bodewes
1
尝试使用openssl pkcs8 -topk8 -nocrypt -in oldfile.pem -out newfile.pem命令,可能也可以使用-outform DER参数。 - Maarten Bodewes
用那个有什么运气?首先将其转换为二进制的PKCS#8格式,然后使用Pkcs8PrivateBlob 应该真的可行。 - Maarten Bodewes
是的,这行代码可以工作。(很抱歉回复晚了,因为其他工作和睡眠阻碍了我。) 现在可以使用 var privatekey = File.ReadAllBytes("newfile.der"); var privkey = CngKey.Import(privatekey, CngKeyBlobFormat.Pkcs8PrivateBlob); var privkeyecdsa = new ECDsaCng(privkey); 来读取 DER 文件。 - RasmusW
1个回答

6
.NET Core 3.0(目前在预览中)有 ECDsa.ImportECPrivateKeyAsymmetricAlgorithm.ImportPkcs8PrivateKeyAsymmetricAlgorithm.ImportEncryptedPkcs8PrivateKey (而RSA有RSAPublicKey和RSAPrivateKey),对于当前文件(BEGIN EC PRIVATE KEY),您需要使用第一个方法。
这些方法的好消息是:它们存在。
坏消息是:它们是下一版本的一部分,而不是当前版本。
好的消息是:下一个版本很快就会成为当前版本。
坏消息是:它们只理解BER / DER数据,而不理解PEM。
最后一点意味着您目前需要查找在-----BEGIN EC PRIVATE KEY-----\n\n-----END EC PRIVATE KEY-----之间的base64内容,并将其解码为二进制格式,然后将其传递给方法。
我所知道支持CNG导入的唯一私钥格式是PKCS8、加密PKCS8和CNG私有格式。要使用CngKey.Import,您首先需要将密钥文件转换为PKCS#8,然后指定格式为Pkcs8PrivateBlob,如评论中建议的那样。

.NET 中是否有任何 PEM 解码实用程序,还是必须使用例如 Bouncy? - Maarten Bodewes
@MaartenBodewes 目前还没有这样的工具。手动编写或使用类似 BouncyCastle 的 PEMParser 是目前的解决方案。也许在下一个版本中,我可以加入符合 RFC 7468 标准的工具(例如忽略 RFC 1421 中的头部部分)。 - bartonjs
3
谢谢@bartonjs,这个方法可行。使用问题描述中提到的原始文件的DER编码版本,我可以执行 var ecdsa = ECDsa.Create(); ecdsa.ImportECPrivateKey(privatekey, out _); ecdsa.VerifyHash(dataToVerify, signature); 。我很确定.NET Core 3.0会在此投入生产之前发布,所以我想我会采用这种方法。 - RasmusW

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接