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

时间:2019-04-01 13:52:29

标签: ssl certificate x509certificate2

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

我没有使用商业SSL证书,而是拥有用于颁发服务器证书的RootCA。这些服务器证书在C#中托管TcpListener时需要其他步骤(我想是因为未使用CSR)...但是,如果我确实拥有私钥和OpenSSL生成/使用的证书,该怎么办。

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

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

我想知道此步骤是否非常必要。有没有办法从Cert组成X509Certificate2,然后应用私钥。构造函数参数仅允许Cert部分使用,但是由于没有私钥,加密然后失败。

此外,我不想依靠OpenSSL或IIS导出pfx。...似乎很笨拙。

理想情况下,我想要:

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

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

2 个答案:

答案 0 :(得分:0)

您要解决的事情有很多不同,难易程度都不同。

为证书附加私钥

从.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)上

,如果您的私钥是RSACryptoServiceProviderDSACryptoServiceProvider,则可以使用cert.PrivateKey = key,但是它具有复杂的副作用,因此不建议使用。

加载私钥

除非您已经解决了这个问题,否则这会很难。

在大多数情况下,答案是在Digital signature in c# without using BouncyCastle中,但是如果可以迁移到.NET Core 3.0,事情将会变得容易得多。

PKCS#8 PrivateKeyInfo

从.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 EncryptedPrivateKeyInfo

从.NET Core 3.0开始,您可以相对简单地做到这一点:

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

(如上所述,如果是PEM,则需要先对其进行“去PEM”操作。)

PKCS#1 RSAPrivateKey

从.NET Core 3.0开始,您可以相对简单地做到这一点:

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

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

答案 1 :(得分:0)

最后我做到了,它运行良好:

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