使用SSLStream进行客户端/服务器验证

时间:2010-09-09 20:04:42

标签: .net authentication ssl sslstream

我有一个客户端和服务器应用程序,它使用SSLStream通过端口80进行通信。客户端和服务器都作为Windows服务运行。

一切都在我的测试环境中运行(我的开发计算机,在OS Windows 7旗舰版下)。我的问题是,当我将客户端和服务器应用程序部署到他们的部署环境(服务器在Windows Server 2008上,而客户端在Windows Server 2003上)时,它不起作用,我收到错误:“客户端和服务器无法通信,因为他们没有共同的算法“ 请注意,我使用makecert命令安装了相同的证书(在下面的“Firstly”部分中列出)

此外,当我放弃尝试让客户端在Windows Server 2003计算机上进行身份验证时,我将其移动到一个全新的/不同的Windows Server 2008计算机..然后出现了一个新的错误。 “提供给包裹的凭证未被识别。”

如果您对此问题有任何经验,请告知。过去3天我一直在研究这个问题,并且已经烧掉了20多个小时的开发时间。 请记住,当服务器和客户端尝试进行身份验证时,问题仍然存在。

首先,我通过makecert.exe使用以下命令生成自签名(?)X509证书:

- makecert -n "CN=Transcert" -r -sv Transcert.pvk Transcert.cer
- makecert -sk Transcert -iv Transcert.pvk -n "CN=Transcert" -ic Transcert.cer Transcert.cer -sr LocalMachine -ss Root 

(请注意,我使用了商店位置'LocalMachine',因为据我所知,Windows服务通过LocalSystem帐户使用此商店位置,我可能错了?)

其次,在服务器上,我通过以下代码从商店检索认证:

X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
X509CertificateCollection cert = store.Certificates.Find(X509FindType.FindBySubjectName, "Transcert", false);
if (cert.Count > 0)
{
  return cert[0];
}

第三,在服务器上,我开始在端口80上侦听TCP客户端:

public virtual void StartListening()
{
  sslServer = new TcpListener(HostPort);

  sslServer.Start();

  AcceptClientThread = new Thread(new ThreadStart(AcceptClientThread_Run));
  AcceptClientThread.Start();
}

private void AcceptClientThread_Run()
{
  try
  {
    TcpClient client = sslServer.AcceptTcpClient();

    ProcessNewClient(client);
  }
  catch (Exception ex)
  {

  }

  AcceptClientThread_Run();
}

第四,在服务器上,我准备代码在客户端连接时进行处理:

  SslClient = pSslClient;
  SSLCertificate = pSSLCertificate;

  _SslStream = new SslStream(SslClient.GetStream());
  _SslStream.AuthenticateAsServer(SSLCertificate, false, SslProtocols.Tls, false);

  Output = new StreamWriter(_SslStream);
  Output.AutoFlush = true;
  Input = new StreamReader(_SslStream);

  ReadThread = new Thread(new ThreadStart(ReadIncomingData));
  ReadThread.Start();

最后,在客户端上,我准备了将客户端连接到服务器的代码:

    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Ssl3;

    sslClient = new TcpClient();
    sslClient.Connect(HostAddress, HostPort);

    //ServicePointManager.ServerCertificateValidationCallback = delegate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };

    sslStream = new SslStream(sslClient.GetStream(), false, new RemoteCertificateValidationCallback(CertificateValidationCallback));
    sslStream.AuthenticateAsClient("Trancert");

    showSslInfo(HostAddress, sslStream, true);

- 以上是我可以解决的这个问题 -

1 个答案:

答案 0 :(得分:1)

如果相同的代码在一台机器上工作而不在另一台机器上,使用相同的服务器证书,那么我会仔细检查私钥是否与第二台机器上的服务器证书一起正确导入。

在证书管理器MMC管理单元中查看证书的属性,您应该会看到“您有一个与此证书对应的私钥”旁边的小键图标。