为了账号安全,请及时绑定邮箱和手机立即绑定

从 Cert 和 Key 创建 X509Certificate2,无需创建 PFX 文件

从 Cert 和 Key 创建 X509Certificate2,无需创建 PFX 文件

C#
小唯快跑啊 2022-11-21 21:33:25

过去,我一直通过导出带密码的 PFX 证书来制作安全的 TcpListener,但我想知道是否可以跳过此步骤。


我没有使用商业 SSL 证书,并且有一个用于颁发服务器证书的根 CA。在 C# 中托管 TcpListener 时,这些服务器证书需要额外的步骤(我猜是因为没有使用 CSR)...但是如果我有私钥和 OpenSSL 生成/使用的证书怎么办。


sslCertificate = new X509Certificate2("myExportedCert.pfx", "1234");

所以这很好,但是我必须发出一个 openssl 命令来从证书和私钥创建一个 pfx 文件,然后输入一些密码。然后将此密码包含在我的代码中。


我想知道这一步是否非常必要。有没有办法从证书中组成 X509Certificate2,然后应用私钥。构造函数参数仅允许证书部分,但加密失败,因为没有私钥。


另外,我不想依赖 OpenSSL 或 IIS 来导出 pfx.... 看起来很笨拙。


理想情况下,我想:


sslCertificate = new X509Certificate2("myCert.crt");

sslCertificate.ApplyPrivateKey(keyBytes) // <= or "private.key" or whatever


sslStream.AuthenticateAsServer(sslCertificate, false, SslProtocols.Default, false);


查看完整描述

2 回答

?
达令说

TA贡献1526条经验 获得超6个赞

您要求的有几件不同的事情,而且容易程度各不相同。


将私钥附加到证书

从 .NET Framework 4.7.2 或 .NET Core 2.0 开始,您可以组合证书和密钥。它不修改证书对象,而是生成一个知道密钥的新证书对象。


using (X509Certificate2 pubOnly = new X509Certificate2("myCert.crt"))

using (X509Certificate2 pubPrivEphemeral = pubOnly.CopyWithPrivateKey(privateKey))

{

    // Export as PFX and re-import if you want "normal PFX private key lifetime"

    // (this step is currently required for SslStream, but not for most other things

    // using certificates)

    return new X509Certificate2(pubPrivEphemeral.Export(X509ContentType.Pfx));

}

在 .NET Framework(但不是 .NET Core)上,如果您的私钥是RSACryptoServiceProvider或者DSACryptoServiceProvider您可以使用cert.PrivateKey = key,但是这有复杂的副作用并且不鼓励。


加载私钥

这个比较难,除非你已经解决了。


大多数情况下,答案是在不使用 BouncyCastle 的情况下使用 c# 中的数字签名,但如果您可以迁移到 .NET Core 3.0,事情就会变得容易得多。


PKCS#8 私钥信息

从 .NET Core 3.0 开始,您可以相对简单地执行此操作:


using (RSA rsa = RSA.Create())

{

    rsa.ImportPkcs8PrivateKey(binaryEncoding, out _);

    // do stuff with the key now

}

(当然,如果您有 PEM,则需要通过提取 BEGIN 和 END 定界符之间的内容并运行它Convert.FromBase64String以获取来“去 PEM”它binaryEncoding)。


PKCS#8 加密私钥信息

从 .NET Core 3.0 开始,您可以相对简单地执行此操作:


using (RSA rsa = RSA.Create())

{

    rsa.ImportEncryptedPkcs8PrivateKey(password, binaryEncoding, out _);

    // do stuff with the key now

}

(如上所述,如果它是 PEM,您需要先“去 PEM”)。


PKCS#1 RSAPprivateKey

从 .NET Core 3.0 开始,您可以相对简单地执行此操作:


using (RSA rsa = RSA.Create())

{

    rsa.ImportRSAPrivateKey(binaryEncoding, out _);

    // do stuff with the key now

}

(如果是 PEM,则为相同的“de-PEM”)。


查看完整回答
反对 回复 2022-11-21
?
翻翻过去那场雪

TA贡献1773条经验 获得超13个赞

最后我这样做了,效果很好:


...

if (!File.Exists(pfx)) {

    // Generate PFX

    string arguments = "openssl pkcs12 -export -in " + certPath + "" + certFile + ".crt -inkey " + certPath + "" + certFile + ".key -out " + certPath + "" + certFile + ".pfx -passout pass:" + pfxPassword;

    ProcessStartInfo opensslPsi = new ProcessStartInfo("sudo", arguments);

    opensslPsi.UseShellExecute = false;

    opensslPsi.RedirectStandardOutput = true;

    using (Process p = Process.Start(opensslPsi)) {

        p.WaitForExit();

    }

    // Set Permission

    ProcessStartInfo chmodPsi = new ProcessStartInfo("sudo", "chmod 644 " + certPath + "" + certFile + ".pfx");

    chmodPsi.UseShellExecute = false;

    chmodPsi.RedirectStandardOutput = true;

    using (Process p = Process.Start(chmodPsi)) {

        p.WaitForExit();

    }

}

sslCertificate = new X509Certificate2(pfx, pfxPassword);

...


查看完整回答
反对 回复 2022-11-21
  • 2 回答
  • 0 关注
  • 6 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信