35

我正在编写一些创建 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 类相关联?

4

4 回答 4

46

您可以省去复制粘贴所有代码的麻烦,并将私钥存储在证书旁边的pfx/pkcs#12文件中:

openssl pkcs12 -export -in my.cer -inkey my.key -out mycert.pfx

您必须提供一个密码,您必须将其传递给以下构造函数X509Certificate2

X509Certificate2 cert = new X509Certificate2("mycert.pfx","password");
于 2014-07-21T11:18:05.230 回答
25

对于其他有同样问题的人,我找到了一段简洁的代码,可以让你做到这一点:

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));
}
于 2013-08-30T09:55:59.220 回答
6

我的解决方案

 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);
于 2020-09-30T16:51:14.110 回答