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

发布于 2024-09-18 15:28:21 字数 2806 浏览 7 评论 0原文

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

在我的测试环境(我的开发计算机,操作系统为 Windows 7 Ultimate)中一切正常。我的问题是,当我将客户端和服务器应用程序部署到其部署环境(服务器位于 Windows Server 2008 上,客户端位于 Windows Server 2003 上)时,它不起作用,并且收到错误:“客户端和服务器无法通信,因为它们不具备通用算法” 请注意,我已经使用 makecert 命令安装了相同的证书(在下面的“首先”部分中列出)。

此外,当我放弃尝试让客户端在 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);

-- 以上是与此问题相关的所有可用内容 --

I have a client and server application which use SSLStream to communicate over port 80. Both the client and the server are running as Windows Services.

Everything works in my test environment (my development computer, under the OS Windows 7 Ultimate). My problem is that when I go to deploy the client and server application to their deployment environments (the server being on Windows Server 2008, and the client being on Windows Server 2003) it does not work, and I get the error: "The client and server cannot communicate, because they do not possess a common algorithm"
Please note that I have installed the same certificate using the makecert commands (listed in the "Firstly" section below)

In addition, when I gave up on trying to get the client to authenticate under the Windows Server 2003 computer, I moved it to a completely new/different Windows Server 2008 computer.. and then got a new error along the lines of "credentials supplied to package not recognized."

If you have any experience with this issue, please advise. I have been working on this for the past 3 days and have burnt up over 20 hours of development time.
Please remember, the problem keeps happening when the Server and Client attempt to authenticate.

Firstly, I used the following commands via makecert.exe to generate self-signed (?) X509 Certificates:

- 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 

(Please note, I used the Store Location 'LocalMachine' because it is my understanding that Windows Services use this Store location through the LocalSystem account, i may be wrong?)

Secondly, On the Server, I retrieve the Certification from the Store by the following code:

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];
}

Thirdly, On the Server, I start listening for TCP Clients on port 80:

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();
}

Fourthly, On the Server, I prepare the code to process when a client connects:

  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();

Finally, On the Client, I prepare the code for connecting the Client to the Server:

    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);

-- Above is everything I have available in relation to this problem --

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

沉睡月亮 2024-09-25 15:28:21

如果相同的代码在一台计算机上运行,​​而在另一台计算机上运行,​​并且具有相同的服务器证书,那么我会仔细检查私钥是否与第二台计算机上的服务器证书一起正确导入。

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

If the same code is working on one machine and not on the other, with the same server certificate, then I would double-check that the private key was imported correctly along with the server certificate on the second machine.

Look at the certificate's properties in the Certificate Manager MMC snap-in, and you should see the tiny key icon next to, "You have a private key that corresponds to this certificate."

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文