C# SSLStream:;调用SSPI失败“;例外情况

C# SSLStream:;调用SSPI失败“;例外情况,c#,mono,.net-2.0,sslstream,sspi,C#,Mono,.net 2.0,Sslstream,Sspi,我有一个奇怪的问题:我用c#编写了一个基于.net2的服务器和客户端,它们通过.net2ssl流聊天。Cl和S之间有一个用于发送命令的连接,Cl和S之间有一个用于发送文件的连接。 在我的windows机器上,本地的一切都很好。但是如果我在Linux服务器上运行服务器(使用mono),共享文件在某些情况下不起作用。我对文件有不同的分类,在3个文件中的2个工作,在第三个文件中,服务器挂起SSLStream.authenticatesServer(…),客户端抛出异常,并显示消息“调用SSPI失败,请


我有一个奇怪的问题:我用c#编写了一个基于.net2的服务器和客户端,它们通过.net2ssl流聊天。Cl和S之间有一个用于发送命令的连接,Cl和S之间有一个用于发送文件的连接。
在我的windows机器上,本地的一切都很好。但是如果我在Linux服务器上运行服务器(使用mono),共享文件在某些情况下不起作用。我对文件有不同的分类,在3个文件中的2个工作,在第三个文件中,服务器挂起
SSLStream.authenticatesServer(…),客户端抛出异常,并显示消息“调用SSPI失败,请参阅内部异常”。
innerexception是System.ComponentModel.Win32Exception,消息为“收到的消息意外或格式错误。”

我认为我在linux上运行它的方式可能是错误的。实际上,我使用VS2012进行本地开发,当我想把它放到服务器上时,我上传了VS编译的exe,并使用
mono server.exe
启动它。但我也尝试在Windows上使用monodevelop来编译它(monodevelop编译的东西在本地也可以使用),并在linux服务器上使用它,但结果是一样的

任何帮助都将不胜感激



这是我的缩写代码:

客户:

//gets auth guid before, then it does
Thread Thre = new Thread(sendfile);
Thre.Start(authguid);


private void sendfile(string guid){
TcpClient cl = new TcpClient();
cl.Connect(hostname, 8789);
SslStream Stream = new SslStream(cl.GetStream(), true, new RemoteCertificateValidationCallback(ServerConnector.ValidateServerCertificate));
Stream.AuthenticateAsClient(hostname);//throws the exception
//sends auth guid and file

}
服务器:

 public class FServer
    {

        protected static bool halt = false;
        protected List<FConnection> connections;
        private TcpListener tcpServer;
        private IPEndPoint ipEnde = new IPEndPoint(IPAddress.Any, 8789);
        private delegate void dlgAccept();
        private dlgAccept accepting;
        private IAsyncResult resAccept;

        public FServer()
        {
            tcpServer = new TcpListener(ipEnde);
            connections = new List<FConnection>();
            tcpServer.Start();
            accepting = new dlgAccept(accept);
            resAccept = accepting.BeginInvoke(null, null);


        }

        public void accept()
        {
            do
            {
                if (tcpServer.Pending())
                    connections.Add(new FConnection(tcpServer.AcceptTcpClient(), this));

                else
                    Thread.Sleep(750);
            } while (!halt && tcpServer != null);
        }

        public class FConnection 
        {
           public SslStream stream;
            //.....some other properties

           public static bool ValidateClientCertificate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
            {
                return true;

            }

            public FConnection(TcpClient cl, FServer inst)
            {
                instance = inst;
                client = cl;

                    stream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateClientCertificate), null);
                    stream.AuthenticateAsServer(instance.mainserver.serverCert, false, SslProtocols.Tls, false);//hangs sometimes on this
                    if (stream.IsAuthenticated && stream.IsEncrypted)
                    {
                    }
                    else
                    {
                        this.Dispose();
                    }

                    //auth and receiving file

            }

        }
    }
公共类FServer
{
受保护的静态bool-halt=false;
受保护的列表连接;
专用TcpListener-tcpServer;
专用IPEndPoint ipEnde=新IPEndPoint(IPAddress.Any,8789);
私有委托void dlgaaccept();
私人接受;
私人IAsyncResult重新接受;
公共FServer()
{
tcpServer=新的TcpListener(ipEnde);
连接=新列表();
tcpServer.Start();
接受=新的DLGAAccept(接受);
resAccept=accepting.BeginInvoke(null,null);
}
公开无效接受()
{
做
{
if(tcpServer.Pending())
添加(新的FConnection(tcpServer.AcceptTcpClient(),this));
其他的
睡眠(750);
}而(!halt&&tcpServer!=null);
}
公共类F连接
{
公共SSL流;
//…其他一些属性
公共静态bool ValidateClientCertificate(对象发送方、X509Certificate证书、X509Chain链、SslPolicyErrors SslPolicyErrors)
{
返回true;
}
公共FConnection(TcpClient cl、FServer inst)
{
实例=inst;
客户=cl;
stream=新的SslStream(client.GetStream(),false,新的RemoteCertificateValidationCallback(ValidateClientCertificate),null);
stream.authenticatesserver(instance.mainserver.serverCert,false,SslProtocols.Tls,false);//有时挂起
if(stream.IsAuthenticated&&stream.IsEncrypted)
{
}
其他的
{
这个。Dispose();
}
//验证和接收文件
}
}
}

好的,我深入研究了innerexception,在这里找到了解决方案:

该信用证由MSDN归于paksys

问题出在客户身上,我改变了

Stream.AuthenticateAsClient(hostname);


我只是有同样的问题,而被接受的答案对我来说并不适用。问题是服务器证书正在使用SHA-2。下面是我用来修复它的代码:

X509Certificates.X509Certificate2Collection xc = new X509Certificates.X509Certificate2Collection();
Stream.AuthenticateAsClient(hostname, xc, Security.Authentication.SslProtocols.Tls12, false);
  • 请注意,与公认答案的唯一区别是sslProtocol

希望它能帮助别人

为什么同样的方法对我不起作用?即使是上面提到的更改,我也会遇到同样的错误。有人能帮我吗?嗨。我也有同样的问题。即使你改变了,问题也没有解决。不知道是否有更多信息?@virtoso您得到的内部异常是什么?内部异常是:客户端客户端和服务器无法通信,因为它们没有通用的算法。
X509Certificates.X509Certificate2Collection xc = new X509Certificates.X509Certificate2Collection();
Stream.AuthenticateAsClient(hostname, xc, Security.Authentication.SslProtocols.Tls12, false);