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

C# - How to Decrypt an Encrypted Private Key with Bouncy Castle

我有一个由 运行:

生成的私钥
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# 中执行此操作。

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

密钥文件如下所示:

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

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

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

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

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

根据您的 .NET 版本,您可能根本不需要 BouncyCastle。从 .NET Core 3.1 开始,PEM 编码的加密密钥有 RSA.ImportEncryptedPkcs8PrivateKey() for DER encoded encrypted private PKCS#8 keys and as of .NET 5.0 there is even RSA.ImportFromEncryptedPem()


否则,使用 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);

可以直接导入 e.g. RSA.ImportParameters().


编辑:
翻了C#/BouncyCastle的源码,你的方法也是可以的(之前不知道)
DecryptKey() 有几个重载,其中一个可以处理 DER 编码的加密密钥,正如 Maarten Bodewes 在他的评论中所怀疑的那样。后者可以很容易地用 Org.BouncyCastle.Utilities.IO.Pem.PemReader() class.
生成 请注意,此 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。