具有可选ClientCertificate的SslStream AuthenticateAsServer

时间:2014-11-14 12:48:18

标签: c# ssl x509certificate sslstream

考虑SslStream.AuthenticateAsServer方法,第二个参数 clientCertificateRequired

如果设置为true,则需要客户端证书。如果没有,它将抛出异常。客户端证书将在 RemoteCertificate 属性中提供。

如果设置为false,则不需要客户端证书,属性 RemoteCertificate 应始终为null。即使一个是由客户提供的。

我想要完成的是让客户决定它是否会提供证书。但是,如果他们确实提供了一个,我想在服务器上知道它。

我试图先将变量设置为true,如果失败,则回退到不需要certificat。但是,这会导致“已经过身份验证的异常”#34;。

try{
        sslStream.AuthenticateAsServer(x509certificate, true, SslProtocols.Tls, true);
}catch(Exception ex){
        sslStream.AuthenticateAsServer(x509certificate, false, SslProtocols.Tls, true);
}

1 个答案:

答案 0 :(得分:2)

我坚信这是一个文档缺陷。

实际上,参数clientCertificateRequired将控制客户端证书是否不被忽略。这意味着:

clientCertificateRequired = false将忽略服务器端的任何客户端证书。不检查证书是否存在或有效性。

clientCertificateRequired = true将尊重服务器端发送的任何客户端证书。如果缺少客户端证书,则使用SslPolicyErrors.RemoteCertificateNotAvailable调用验证回调,这会导致在使用默认实现时捕获的异常。

所以在你的情况下:将clientCertificateRequired设置为true并实现自定义验证回调,如下所示:

var client = server.AcceptTcpClient()
var networkStream = client.GetStream()

var sslStream = new SslStream(
    networkStream,
    false,
    (sender, certificate, chain, errors) =>
    {
        if (errors == SslPolicyErrors.None)
        {
            return true;
        }

        if (errors == SslPolicyErrors.RemoteCertificateNotAvailable)
        {
            // seems to be okay for you
            return true;
        }

        return false;
    },
    (sender, host, certificates, certificate, issuers) => x509certificate
);

sslStream.AuthenticateAsServer(x509certificate, true, SslProtocols.Tls, true);
相关问题