C# - 如何使用Bouncy Castle解密加密的私钥

6

我有一个私钥,是通过运行以下命令生成的:

openssl req -new -sha384 -x509 -days 63524 -subj "/C=CA/ST=State/L=City/O=Org/CN=Org-CA" -extensions v3_ca -keyout Org-CA.key -out Org-CA.pem -passout pass:pass1234

我需要使用这个私钥和证书来签名客户端的CSR。以前我用OpenSSL完成这个工作,但现在我需要使用C#来做。

我在网上找到了一些我想要做的示例,但是这些示例都是使用Bouncy Castle和未加密的私钥。

这个密钥文件看起来像这样:

-----BEGIN ENCRYPTED PRIVATE KEY-----
....
-----END ENCRYPTED PRIVATE KEY-----

我正在尝试通过以下方式加载它:

var privatekey = File.ReadAllBytes(@"Org-CA.key");
var rsaKeyParameters = PrivateKeyFactory.DecryptKey("pass1234".ToArray(), privatekey);

但是这种方法不起作用。我收到一个错误消息,显示序列中的元素数量错误(参数“seq”)

我应该如何解密和加载私钥?


你可以使用类似 new X509Certificate2(fileName, pw)GetECDsaPrivateKey()Export() 的方法从证书中提取密钥。同时,也可以查看一下 RSA.Create(4096) - Charles
我非常确定普通方法期望一个DER编码结构。这样的结构通常至少包含一个SEQUENCE,因此会出现错误。您首先需要解析PEM或找到一个处理PEM的实用函数。 - Maarten Bodewes
1个回答

2
根据您的 .NET 版本,您可能根本不需要 BouncyCastle。从 .NET Core 3.1 开始,可以使用 RSA.ImportEncryptedPkcs8PrivateKey() 导入 DER 编码的加密私有 PKCS#8 密钥,而从 .NET 5.0 开始,甚至可以使用 RSA.ImportFromEncryptedPem() 导入 PEM 编码的加密密钥。
否则,使用 C# / BouncyCastle 可用于导入加密的私有 PKCS#8 密钥,例如:
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
...
string encPkcs8 = @"-----BEGIN ENCRYPTED PRIVATE KEY-----
                    ...
                    -----END ENCRYPTED PRIVATE KEY-----"; 
StringReader stringReader = new StringReader(encPkcs8);
PemReader pemReader = new PemReader(stringReader, new PasswordFinder("<your password>"));
RsaPrivateCrtKeyParameters keyParams = (RsaPrivateCrtKeyParameters)pemReader.ReadObject();
...

使用以下实现的 IPasswordFinder 接口:

private class PasswordFinder : IPasswordFinder
{
    private string password;
    public PasswordFinder(string pwd) => password = pwd;
    public char[] GetPassword() => password.ToCharArray();
}

如果需要的话,可以通过以下方式将keyParams转换为System.Security.Cryptography.RSAParameters:
using Org.BouncyCastle.Security;
...
RSAParameters rsaParameters = DotNetUtilities.ToRSAParameters(keyParams);

可以直接导入,例如使用RSA.ImportParameters()


编辑:
在查看C#/BouncyCastle源代码后,您的方法也是可行的(我之前不知道)。
DecryptKey()有多个重载,其中一个可以处理Maarten Bodewes在评论中已经怀疑的DER编码加密密钥。后者可以使用Org.BouncyCastle.Utilities.IO.Pem.PemReader()类轻松生成。
请注意,此PemReader与第一种实现中的PemReader不同(不同的命名空间),这就是为什么我在以下代码片段中明确使用命名空间的原因。通过这种方法,可以生成RsaPrivateCrtKeyParameters实例,如下所示:

using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto.Parameters;
...
StringReader stringReader = new StringReader(encPkcs8);
Org.BouncyCastle.Utilities.IO.Pem.PemReader pemReader = new Org.BouncyCastle.Utilities.IO.Pem.PemReader(stringReader);
Org.BouncyCastle.Utilities.IO.Pem.PemObject pem = pemReader.ReadPemObject();
RsaPrivateCrtKeyParameters keyParams = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.DecryptKey("<your password>".ToCharArray(), pem.Content);
...

pem.Content 包含 DER 编码的加密私钥 PKCS#8。


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