使用OpenSSL .Net检索证书

7
我想使用OpenSSL .Net包装器将远程服务器上的证书检索到我的C#代码中。基本上,我想复制。
openssl s_client -connect 192.168.254.13:636 -showcerts

“..并最终将结果带入X509证书。这可行吗?如果可以的话,有谁能指点我正确的方向吗?”
4个回答

7
我认为这个问题有两个部分:
  1. 如何检索服务器的证书
  2. 如何检索证书链
要检索服务器的证书,您可以使用SslStream,其方法类似于.NET自己的SslStream
var serverName = "...;
var client = new TcpClient(serverName, 443);            

// Create an SSL stream that will close the client's stream.
using (var sslStream = new SslStream(client.GetStream(),true))
{
    sslStream.AuthenticateAsClient(serverName);                
    var serverCertificate = sslStream.RemoteCertificate;
 }

看起来 OpenSSL.Net 无法检索证书链。-showcerts 参数使用的 SSL_get_peer_cert_chain 函数在 OpenSSL.NET 中未实现。
如果您不介意混用 OpenSSL.Net 和内置的 .NET 类,可以将 OpenSSL.Net 证书转换为 .NET 证书,并使用 .NET 的 X509Chain.Build 检索链。您可以使用 .NET 证书的 RawData 属性将 .NET 证书转换回 OpenSSL.NET 证书。
var managedCert = new System.Security.Cryptography.X509Certificates.X509Certificate2(serverCertificate.DER);
var chain = new System.Security.Cryptography.X509Certificates.X509Chain();
chain.Build(managedCert);


foreach (var element in chain.ChainElements)
{
    var raw = element.Certificate.RawData;
    using (var bio = new BIO(raw))
    {
        var oc = OpenSSL.X509.X509Certificate.FromDER(bio);
    }
}

也许你可以使用.NET的SslStream和X509Certificate2对象,使用原始证书数据而不使用OpenSSL.Net来实现你想要的功能。

使用特定的CA证书进行SSL连接,可避免使用Windows证书存储中的CA动物园进行验证。但您必须提供一个受信任的CA证书来验证证书链。如果您知道颁发证书的CA证书,最好只使用该CA证书,而不是其他数百个可用的CA证书。 - jww
@jww,你的建议存在安全风险,已经被多次利用——最近就是由于Heartbleed漏洞的影响。CA证书过去曾被泄露和吊销。通过使用本地存储作为CA,你无法验证证书或知道它是否已被吊销。没有所谓的“CA动物园”,这只是证书工作的方式。 - Panagiotis Kanavos
@Panagiotis - Peter Guttman在他的《Engineering Security》一书中谈到了CA Zoo等内容。这是一本很棒的读物,我建议你浏览一下。特别是第1章和第6章关于PKI的部分。我已经记不起上一次我依赖CA Zoo是什么时候了。CA Zoo为我们带来了DigiNotar为Google、Hotmail、Yahoo等发放证书以及愚蠢的客户端接受这些证书。这是一个不可接受且可以预防的失败。 - jww

2

很抱歉,这对我来说不太适用 - 我想使用OpenSSL从非HTTPS服务中检索证书。 - KenD

2
为了创建与s_client相同的功能,您可能需要查看s_client的代码。
您可以在openssl-X.Y.Z.tar.gz / apps / s_client.c中找到s_client。
可能PEM_write_bio_X509会执行X509Certificate的“打印”:
if (c_showcerts)
    PEM_write_bio_X509(bio,sk_X509_value(sk,i));
}

但是还有连接部分... ftp://ftp.openssl.org/source/openssl-1.0.1.tar.gz

我本来希望能够使用OpenSSL.net以某种“简单”的方式完成它,但似乎不行:( - KenD

1
要获取CRL,请首先检查证书及其颁发证书是否包含一个包含URI GeneralName的cRLDistributionPoints扩展。该扩展在RFC 3280中定义,并指定了CA通信与用于颁发另一个证书的证书相对应的CRL的位置的方式。不幸的是,该扩展被定义为可选项,大多数根CA都不使用它。

我不确定这与我的原始问题有什么关系?我对CRL不感兴趣,我想获取的是“原始”证书... - KenD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接