我正在尝试编写一个客户端-服务器库,让我的 LAN 计算机相互通信。由于这主要是一种自我教育尝试,因此我试图通过 SSL 进行这些连接。我的计划是维护一台主机,并让每个客户端都为主机维护一个相互验证的 System.Net.SslStream 实例。主机代码看起来(粗略地说)是这样的(为简洁起见,省略了错误处理):
SslStream newStream = null;
newStream = new SslStream(this.client.GetStream(), false);
newStream.AuthenticateAsServer(
this.Certificate as X509Certificate,
true,
System.Security.Authentication.SslProtocols.Tls,
false);
if (!(
newStream.IsMutuallyAuthenticated &&
newStream.IsEncrypted &&
newStream.IsSigned))
{
throw new AuthenticationException("Authentication results unsatisfactory.");
}
其中,this.Certificate
是一个 X509Certificate2。客户端代码如下所示:
SslStream connectionStream = new SslStream(this.client.GetStream(), false);
connectionStream.AuthenticateAsClient(
this.ServerHostname,
new X509CertificateCollection(new X509Certificate[] { (X509Certificate)this.Certificate }),
SslProtocols.Tls,
false);
if (!(
connectionStream.IsEncrypted &&
connectionStream.IsMutuallyAuthenticated &&
connectionStream.IsSigned))
{
throw new AuthenticationException("Authentication results unsatisfactory");
}
我已经按照这篇文章的说明生成了客户端和服务器证书,并将根权限安装到客户端和服务器上本地计算机的受信任的权限中。然后,我为客户端和服务器生成证书,将 .cer 文件的副本放在客户端/服务器可访问的位置(加载以获取 X509Certificate 对象),并在各自机器的个人存储中安装带有私钥的文件。现在,当客户端和服务器在同一台机器上时,一切正常。但是当我生成一个新证书并将其放在第二台机器上时,客户端和服务器现在无法相互验证。连接已建立、加密和签名,但 IsMutuallyAuthenticated 为假。我怎样才能解决这个问题?我究竟做错了什么?
编辑:LocalCertificateSelectionCallback 和另一个回调告诉我客户端找到一个本地证书,这是我的,没有远程证书,也没有可接受的颁发者。我的证书被选中并从本地证书选择中返回。客户端没有 SSL 策略错误,在主机端,我仍然得到 RemoteCertificateNotAvailable。用 Wireshark 嗅探这个事务,我看到一个标准的 TCP 握手,然后是几百字节的乱码,其中包括主机证书的名称,然后是 FIN、ACK 数据包,这些数据包标志着事务的结束。所以客户端证书确实没有被发送,即使它是由 LocalCertificateSelectionCallback 例程选择的。什么可能导致这种情况?我该如何解决?