从 Cert 和 Key 创建 X509Certificate2,无需创建 PFX 文件
Create X509Certificate2 from Cert and Key, without making a PFX file
过去我一直通过导出带密码的 PFX 证书来制作安全的 TcpListener,但想知道是否可以跳过此步骤。
我没有使用商业 SSL 证书,并且有一个用于颁发服务器证书的根 CA。在 C# 中托管 TcpListener 时,这些服务器证书需要额外的步骤(我猜是因为没有使用 CSR)...但是如果我有私钥和 OpenSSL generates/uses.[=12 的证书怎么办? =]
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);
您要求的有几项不同的要求,而且难易程度也不同。
将私钥附加到证书
从 .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
,但这有复杂的副作用并且是气馁。
正在加载私钥
这个比较难,除非你已经解决了。
在大多数情况下,答案在 Digital signature in c# without using BouncyCastle 中,但如果您可以迁移到 .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,你需要 "de-PEM" 它,通过提取 BEGIN 和 END 定界符之间的内容,并通过 Convert.FromBase64String
运行 它,以便得到 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,则需要先 "de-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")。
最后我这样做了,效果很好:
...
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);
...
过去我一直通过导出带密码的 PFX 证书来制作安全的 TcpListener,但想知道是否可以跳过此步骤。
我没有使用商业 SSL 证书,并且有一个用于颁发服务器证书的根 CA。在 C# 中托管 TcpListener 时,这些服务器证书需要额外的步骤(我猜是因为没有使用 CSR)...但是如果我有私钥和 OpenSSL generates/uses.[=12 的证书怎么办? =]
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);
您要求的有几项不同的要求,而且难易程度也不同。
将私钥附加到证书
从 .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
,但这有复杂的副作用并且是气馁。
正在加载私钥
这个比较难,除非你已经解决了。
在大多数情况下,答案在 Digital signature in c# without using BouncyCastle 中,但如果您可以迁移到 .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,你需要 "de-PEM" 它,通过提取 BEGIN 和 END 定界符之间的内容,并通过 Convert.FromBase64String
运行 它,以便得到 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,则需要先 "de-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")。
最后我这样做了,效果很好:
...
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);
...