简体   繁体   English

从证书和密钥创建 X509Certificate2,无需制作 PFX 文件

[英]Create X509Certificate2 from Cert and Key, without making a PFX file

In the past I have been making secure TcpListener by exporting a PFX certificate with a password, but would like to know if this step could be skipped.过去,我一直通过导出带有密码的 PFX 证书来制作安全的 TcpListener,但想知道是否可以跳过此步骤。

I'm not using commercial SSL certificates, and have a Root CA, that I use to issue server certificates.我没有使用商业 SSL 证书,并且有一个用于颁发服务器证书的根 CA。 These server certificates require additional steps when hosting a TcpListener in C# (I guess because the CSR wasn't used)... but what if I do have the Private Key, and the Certificate that OpenSSL generates/uses.在 C# 中托管 TcpListener 时,这些服务器证书需要额外的步骤(我猜是因为没有使用 CSR)……但是如果我有私钥和 OpenSSL 生成/使用的证书怎么办。

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

So this is great, however I have to issue an openssl command to make a pfx file from the Certificate and the Private Key, then make up some password.所以这很棒,但是我必须发出 openssl 命令从证书和私钥制作 pfx 文件,然后制作一些密码。 Then include this password in my code.然后在我的代码中包含这个密码。

I was wondering if this step was quite necessary.我想知道这一步是否很有必要。 Is there a way to make up a X509Certificate2 from the Cert, and then apply the Private Key.有没有办法从证书中组成一个X509Certificate2,然后应用私钥。 The constructor arguments allow the Cert only part, but encrypting fails then because there is no private key.构造函数参数只允许 Cert 部分,但加密失败,因为没有私钥。

Also, I don't want to rely on OpenSSL or IIS to export the pfx.... seems clumsy.另外,我不想依赖 OpenSSL 或 IIS 来导出 pfx.... 看起来很笨拙。

Ideally i would like:理想情况下,我想:

sslCertificate = new X509Certificate2("myCert.crt");
sslCertificate.ApplyPrivateKey(keyBytes) // <= or "private.key" or whatever

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

There are a couple of different things you're asking for, with different levels of ease.有几种不同的东西,你要求,不同程度的轻松。

Attaching a private key to a certificate将私钥附加到证书

Starting in .NET Framework 4.7.2 or .NET Core 2.0 you can combine a cert and a key.从 .NET Framework 4.7.2 或 .NET Core 2.0 开始,您可以组合证书和密钥。 It doesn't modify the certificate object, but rather produces a new cert object which knows about the key.它不会修改证书对象,而是生成一个知道密钥的新证书对象。

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));
}

on .NET Framework (but not .NET Core) if your private key is RSACryptoServiceProvider or DSACryptoServiceProvider you can use cert.PrivateKey = key , but that has complex side-effects and is discouraged.在 .NET Framework(但不是 .NET Core)上,如果您的私钥是RSACryptoServiceProviderDSACryptoServiceProvider您可以使用cert.PrivateKey = key ,但这会产生复杂的副作用,因此不鼓励使用。

Loading the private key加载私钥

This one is harder, unless you've already solved it.这个更难,除非你已经解决了。

For the most part the answer for this is in Digital signature in c# without using BouncyCastle , but if you can move to .NET Core 3.0 things get a lot easier.大多数情况下,答案是在c# 中使用数字签名而不使用 BouncyCastle ,但是如果您可以迁移到 .NET Core 3.0,事情就会变得容易得多

PKCS#8 PrivateKeyInfo PKCS#8 私钥信息

Starting in .NET Core 3.0 you can do this relatively simply:从 .NET Core 3.0 开始,您可以相对简单地执行此操作:

using (RSA rsa = RSA.Create())
{
    rsa.ImportPkcs8PrivateKey(binaryEncoding, out _);
    // do stuff with the key now
}

(of course, if you had a PEM you need to "de-PEM" it, by extracting the contents between the BEGIN and END delimiters and running it through Convert.FromBase64String in order to get binaryEncoding ). (当然,如果你有一个 PEM,你需要通过提取 BEGIN 和 END 分隔符之间的内容并通过Convert.FromBase64String运行它来“de-PEM”它以获得binaryEncoding )。

PKCS#8 EncryptedPrivateKeyInfo PKCS#8 加密私钥信息

Starting in .NET Core 3.0 you can do this relatively simply:从 .NET Core 3.0 开始,您可以相对简单地执行此操作:

using (RSA rsa = RSA.Create())
{
    rsa.ImportEncryptedPkcs8PrivateKey(password, binaryEncoding, out _);
    // do stuff with the key now
}

(as above, you need to "de-PEM" it first, if it was PEM). (如上所述,如果它是 PEM,您需要先“取消 PEM”)。

PKCS#1 RSAPrivateKey PKCS#1 RSAPrivateKey

Starting in .NET Core 3.0 you can do this relatively simply:从 .NET Core 3.0 开始,您可以相对简单地执行此操作:

using (RSA rsa = RSA.Create())
{
    rsa.ImportRSAPrivateKey(binaryEncoding, out _);
    // do stuff with the key now
}

(same "de-PEM" if PEM). (如果 PEM,则相同的“de-PEM”)。

In the end i did this, and it works fine:最后我做了这个,它工作正常:

...
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);
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM