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

Zeu*_*s82 6 .net c# encryption bouncycastle .net-core

我有一个通过运行生成的私钥:

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
Run Code Online (Sandbox Code Playgroud)

我需要使用此私钥和证书来签署客户端 CSR。我曾经使用 OpenSSL 来执行此操作,但我需要在 C# 中执行此操作。

我在网上找到了我想要做的事情的示例,但这些示例使用的是充气城堡和未加密的私钥。

密钥文件如下所示:

-----BEGIN ENCRYPTED PRIVATE KEY-----
....
-----END ENCRYPTED PRIVATE KEY-----
Run Code Online (Sandbox Code Playgroud)

我正在尝试通过这样做来加载它:

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

但这不起作用。我收到一条错误消息Wrong number of elements in sequence (Parameter 'seq')'

这是我应该解密和加载私钥的方式吗?

Top*_*aco 3

根据您的 .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();
...
Run Code Online (Sandbox Code Playgroud)

接口的以下实现IPasswordFinder

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

如有必要,可以通过以下方式从keyParams到进行转换:System.Security.Cryptography.RSAParameters

using Org.BouncyCastle.Security;
...
RSAParameters rsaParameters = DotNetUtilities.ToRSAParameters(keyParams);
Run Code Online (Sandbox Code Playgroud)

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


编辑:
在深入研究 C#/BouncyCastle 源代码后,你的方法也是可能的(我之前不知道)。
DecryptKey()有几个重载,其中之一可以处理 DER 编码的加密密钥,正如 Maarten Bodewes 在他的评论中已经怀疑的那样。后者可以通过Org.BouncyCastle.Utilities.IO.Pem.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);
...
Run Code Online (Sandbox Code Playgroud)

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