禁用AuthenticateAsServer的证书验证似乎不起作用

时间:2016-07-10 14:05:16

标签: c# ssl client-certificates

我正在开发一个更大的C#套接字应用,它将通过SSL使用服务器和客户端身份验证。为了在我的本地机器上测试应用程序的其他部分,我需要禁用认证验证。我已经尝试重写ServerCertificateValidatioNCallback,如其他一些地方所建议但我继续得到一个例外。我正在测试使用OpenSSL创建的自签名证书。

我试过的解决方案的文章:

我得到的例外:

StackTrace:    at System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, Exception exception)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Net.Security.SslStream.AuthenticateAsServer(X509Certificate serverCertificate, Boolean clientCertificateRequired, SslProtocols enabledSslProtocols, Boolean checkCertificateRevocation)

我已将服务器代码缩减为以下内容:

 ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
 X509Certificate2 cert = new X509Certificate2("server.pfx", "password");

 IPAddress ip = IPAddress.Parse("127.0.0.1");
 TcpListener server = new TcpListener(ip, 8000);
 server.Start();

 TcpClient client = server.AcceptTcpClient();
 Console.WriteLine(client.Client.RemoteEndPoint.ToString() + ":" + ((IPEndPoint)client.Client.RemoteEndPoint).Port + " connected");
 SslStream ssl = new SslStream(client.GetStream(), false);
 ssl.AuthenticateAsServer(cert, true, SslProtocols.Tls, false);

客户端代码如下:

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
TcpClient client = new TcpClient("127.0.0.1", 8000);
X509Certificate2Collection coll = new X509Certificate2Collection();
coll.Add(new X509Certificate2("client.pfx", "password"));
byte[] data = Encoding.UTF8.GetBytes("Hello from the client!");

using (SslStream ssl = new SslStream(client.GetStream(), false))
{
  ssl.AuthenticateAsClient("127.0.0.1", coll, SslProtocols.Tls, false);
  ssl.Write(data, 0, data.Length);
  data = new Byte[8192];
  int bytes = 0;
  string resp = "";

  do
  {
    bytes = ssl.Read(data, 0, data.Length);
    if (bytes > 0) resp += System.Text.Encoding.ASCII.GetString(data, 0, bytes);
  }
  while (bytes > 0);

  Console.WriteLine("Response: " + resp);
}

client.Close();

AuthenticateAsServer和AuthenticateAsClient发生异常。应用程序的设计需要使用客户端证书。

我尝试将PFX文件导入证书存储区,结果没有任何区别。

我还尝试使用makecert重新创建自签名证书和私钥,并使用pvk2pfx.exe转换为PFX,结果没有任何区别。我的想法是,这可能是他们在另一台机器上创建的问题。

1 个答案:

答案 0 :(得分:2)

显然这条线还不够:

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

我不得不改变我的SslStream: (服务器)

SslStream ssl = new SslStream(client.GetStream(), false);

和(客户)

using (SslStream ssl = new SslStream(client.GetStream(), false))

要: (服务器)

SslStream ssl = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateCert));

和(客户)

using (SslStream ssl = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateCert)))

并添加以下方法:

public static bool ValidateCert(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    return true; // Allow untrusted certificates.
}

显然,这优先于:ServicePointManager.ServerCertificateValidationCallback委托。

显然,我现在需要弄清楚如何修改ValidateCert以选择性地允许不受信任的证书与否。