将私钥与 .net 中的 X509Certificate2 类关联
Posted
技术标签:
【中文标题】将私钥与 .net 中的 X509Certificate2 类关联【英文标题】:Associate a private key with the X509Certificate2 class in .net 【发布时间】:2013-08-30 00:02:14 【问题描述】:我正在编写一些创建 X509 证书和公钥/私钥对的代码。公钥被添加到证书中,并发送给对其进行签名的 CA。
然后通过 System.Security.Cryptography.X509Certificates.X509Certificate2 类访问返回的证书。现在我想使用这个证书来启动与其他客户端的安全连接。因此我使用 SslStream 类。要启动 SSL 握手,我使用以下方法:
server.AssociatedSslStream.AuthenticateAsServer(
MyCertificate, // Client Certificate
true, // Require Certificate from connecting Peer
SslProtocols.Tls, // Use TLS 1.0
false // check Certificate revocation
);
此方法要求私钥与证书相关联。当然 CA 返回的证书不包含私钥。但它作为 .key 文件存储在硬盘上。 X509Certificate2 类有一个名为 PrivateKey 的属性,我猜它会将私钥与证书相关联,但我找不到设置此属性的方法。
有什么方法可以将私钥与 .net X509 类关联起来?
【问题讨论】:
这能回答你的问题吗? Providing an EC private key to certificate for use in HttpClient C# 【参考方案1】:您可以省去复制粘贴所有代码的麻烦,并将私钥存储在证书旁边的 pfx
/pkcs#12
文件中:
openssl pkcs12 -export -in my.cer -inkey my.key -out mycert.pfx
你必须提供一个密码,你必须将它传递给X509Certificate2
的构造函数:
X509Certificate2 cert = new X509Certificate2("mycert.pfx","password");
【讨论】:
这救了我!创建了 pfx,但没有意识到我还需要向构造函数提供该密码。 出色的答案!我用它来避免通过 MMC 插件注册证书的麻烦。 您可以通过在openSSL命令中添加“-passout pass:”来避免密码 这应该被标记为真正的答案,因为它是做到这一点的真正方式。 从哪里获得 openssl?【参考方案2】:对于遇到相同问题的其他人,我找到了一段简洁的代码,可以让你做到这一点:
http://www.codeproject.com/Articles/162194/Certificates-to-DB-and-Back
byte[] certBuffer = Helpers.GetBytesFromPEM(publicCert, PemStringType.Certificate);
byte[] keyBuffer = Helpers.GetBytesFromPEM(privateKey, PemStringType.RsaPrivateKey);
X509Certificate2 certificate = new X509Certificate2(certBuffer, password);
RSACryptoServiceProvider prov = Crypto.DecodeRsaPrivateKey(keyBuffer);
certificate.PrivateKey = prov;
编辑:Helper 方法的代码(否则需要 codeproject 登录)如下:
public static byte[] GetBytesFromPEM(string pemString, PemStringType type)
string header; string footer;
switch (type)
case PemStringType.Certificate:
header = "-----BEGIN CERTIFICATE-----";
footer = "-----END CERTIFICATE-----";
break;
case PemStringType.RsaPrivateKey:
header = "-----BEGIN RSA PRIVATE KEY-----";
footer = "-----END RSA PRIVATE KEY-----";
break;
default:
return null;
int start = pemString.IndexOf(header) + header.Length;
int end = pemString.IndexOf(footer, start) - start;
return Convert.FromBase64String(pemString.Substring(start, end));
【讨论】:
这是一个比将私钥和证书捆绑在一起更好的方法,我使用了这个选项并发现它是一个更好的选择。 如果您能告诉我们这种优越性的本质吗? 确实包含辅助方法的代码,烦人必须在外部站点上创建用户才能访问。 尝试使用它,但是(当然)没有加密类(System.Web.Helpers 中有一个 - 很确定不是......)这里缺少使用? 尝试在 .NET Core 2 控制台应用程序中设置证书的私钥时,我收到了PlatformNotSupportedException
。【参考方案3】:
我的解决方案
byte[] PublicCertificate = Encoding.Unicode.GetBytes("-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----");
var publicCertificate = new X509Certificate2(PublicCertificate );
byte[] PrivateKey = Convert.FromBase64String("MIIEvQIBA...=");
using var rsa = RSA.Create();
rsa.ImportPkcs8PrivateKey(PrivateKey, out _);
publicCertificate = publicCertificate.CopyWithPrivateKey(rsa);
publicCertificate = new X509Certificate2(publicCertificate.Export(X509ContentType.Pkcs12));
var client = new RestClient("api_url");
client.ClientCertificates = new X509Certificate2Collection();
client.ClientCertificates.Add(publicCertificate);
【讨论】:
ImportPkcs8PrivateKey
是 .NET Core - 在 .NET Framework 4.8 中不可用?
@Jaans docs.microsoft.com/pt-br/dotnet/api/…【参考方案4】:
.NET 5+
X509Certificate2.CreateFromPemFile(certPath, keyPath);
https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.x509certificate2.createfrompemfile?view=net-5.0#System_Security_Cryptography_X509Certificates_X509Certificate2_CreateFromPemFile_System_String_System_String_
【讨论】:
以上是关于将私钥与 .net 中的 X509Certificate2 类关联的主要内容,如果未能解决你的问题,请参考以下文章
使用 RSA SHA 256 对字符串进行签名,仅将私钥作为字符串 .NET