在 C# 中以编程方式将 .crt + .key 文件转换为 X509Certificate2
Convert .crt + .key files to X509Certificate2 programmatically in C#
我在 Linux 机器上有一个 .crt 证书和一个 .key 私钥文件。私钥采用加密的 PKCS#8 格式(BEGIN ENCRYPTED PRIVATE KEY...)。我想将它们导入 X509Certificate2 对象以供进一步使用。由于我们在 Linux,我们正在使用 .NET Core 2.2(我们还不能迁移到 3.0)。
我探索了一些可能的解决方案,详情如下:
- 使用
openssl
将文件转换为 .pfx 并使用 X509Certificate2 导入
- 我不想使用此选项,因为我不想从 C# 中执行 shell 代码。我希望在 C# 中完全以编程方式实现解决方案。
- 使用 C# BouncyCastle 库执行以下任一操作:
- 将证书和密钥都转换为 .pfx(如上所述),或者
- 分别导入证书和私钥,并使用
X509Certificate2.CopyWithPrivateKey()
组合。
- 但是,我找不到 API 的 BouncyCastle C# 版本,所以我不确定我可以使用什么方法来做到这一点。
- 我在此处遗漏的其他一些 C# 编程方法
本质上,最终目标是从 .crt 和 .key 文件中获取 X509Certificate2 对象。任何 help/insight 关于使用什么方法,甚至指向有用的 BouncyCastle 文档的指针,都将不胜感激。谢谢!
这在 .NET Core 3.0 中是可能的,尽管不是那么友好:
private static byte[] UnPem(string pem)
{
// This is a shortcut that assumes valid PEM
// -----BEGIN words-----\nbase64\n-----END words-----
const string Dashes = "-----";
int index0 = pem.IndexOf(Dashes);
int index1 = pem.IndexOf('\n', index0 + Dashes.Length);
int index2 = pem.IndexOf(Dashes, index1 + 1);
return Convert.FromBase64String(pem.Substring(index1, index2 - index1));
}
...
string keyPem = File.ReadAllText("private.key");
byte[] keyDer = UnPem(keyPem);
X509Certificate2 certWithKey;
using (X509Certificate2 certOnly = new X509Certificate2("certificate.cer"))
using (RSA rsa = RSA.Create())
{
// For "BEGIN PRIVATE KEY"
rsa.ImportPkcs8PrivateKey(keyDer, out _);
certWithKey = certOnly.CopyWithPrivateKey(rsa);
}
using (certWithKey)
{
Console.WriteLine(certWithKey.HasPrivateKey);
}
RSA 私钥可以采用三种不同的格式,您需要为每种格式调用正确的导入:
- "BEGIN PRIVATE KEY": ImportPkcs8PrivateKey
- "BEGIN ENCRYPTED PRIVATE KEY":ImportEncryptedPkcs8PrivateKey
- "BEGIN RSA PRIVATE KEY":导入RSAPrivateKey
在 .NET 5 中,这变得尽可能简单:
var certificate =
X509Certificate2.CreateFromPemFile(
crtFile,
Path.ChangeExtension(crtFile, "key"));
我在 Linux 机器上有一个 .crt 证书和一个 .key 私钥文件。私钥采用加密的 PKCS#8 格式(BEGIN ENCRYPTED PRIVATE KEY...)。我想将它们导入 X509Certificate2 对象以供进一步使用。由于我们在 Linux,我们正在使用 .NET Core 2.2(我们还不能迁移到 3.0)。
我探索了一些可能的解决方案,详情如下:
- 使用
openssl
将文件转换为 .pfx 并使用 X509Certificate2 导入- 我不想使用此选项,因为我不想从 C# 中执行 shell 代码。我希望在 C# 中完全以编程方式实现解决方案。
- 使用 C# BouncyCastle 库执行以下任一操作:
- 将证书和密钥都转换为 .pfx(如上所述),或者
- 分别导入证书和私钥,并使用
X509Certificate2.CopyWithPrivateKey()
组合。 - 但是,我找不到 API 的 BouncyCastle C# 版本,所以我不确定我可以使用什么方法来做到这一点。
- 我在此处遗漏的其他一些 C# 编程方法
本质上,最终目标是从 .crt 和 .key 文件中获取 X509Certificate2 对象。任何 help/insight 关于使用什么方法,甚至指向有用的 BouncyCastle 文档的指针,都将不胜感激。谢谢!
这在 .NET Core 3.0 中是可能的,尽管不是那么友好:
private static byte[] UnPem(string pem)
{
// This is a shortcut that assumes valid PEM
// -----BEGIN words-----\nbase64\n-----END words-----
const string Dashes = "-----";
int index0 = pem.IndexOf(Dashes);
int index1 = pem.IndexOf('\n', index0 + Dashes.Length);
int index2 = pem.IndexOf(Dashes, index1 + 1);
return Convert.FromBase64String(pem.Substring(index1, index2 - index1));
}
...
string keyPem = File.ReadAllText("private.key");
byte[] keyDer = UnPem(keyPem);
X509Certificate2 certWithKey;
using (X509Certificate2 certOnly = new X509Certificate2("certificate.cer"))
using (RSA rsa = RSA.Create())
{
// For "BEGIN PRIVATE KEY"
rsa.ImportPkcs8PrivateKey(keyDer, out _);
certWithKey = certOnly.CopyWithPrivateKey(rsa);
}
using (certWithKey)
{
Console.WriteLine(certWithKey.HasPrivateKey);
}
RSA 私钥可以采用三种不同的格式,您需要为每种格式调用正确的导入:
- "BEGIN PRIVATE KEY": ImportPkcs8PrivateKey
- "BEGIN ENCRYPTED PRIVATE KEY":ImportEncryptedPkcs8PrivateKey
- "BEGIN RSA PRIVATE KEY":导入RSAPrivateKey
在 .NET 5 中,这变得尽可能简单:
var certificate =
X509Certificate2.CreateFromPemFile(
crtFile,
Path.ChangeExtension(crtFile, "key"));