我正在研究一些创建X509certificate和公钥/私钥对的代码。公钥被添加到证书中,并将其发送给签名的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类关联起来吗?
答案 0 :(得分:30)
您可以省去复制粘贴所有代码的麻烦,并将证书旁边的私钥存储在pfx
/ pkcs#12
文件中:
openssl pkcs12 -export -in my.cer -inkey my.key -out mycert.pfx
您必须提供密码,您必须将密码传递给X509Certificate2
的构造函数:
X509Certificate2 cert = new X509Certificate2("mycert.pfx","password");
答案 1 :(得分:16)
对于遇到同样问题的其他人,我发现了一个简洁的代码片段,让你完全按照这个原则进行操作:
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方法的代码(否则需要代码项目登录)如下:
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));
}
答案 2 :(得分:2)
我的解决方案
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);