带有客户端身份验证的.Net和Java之间的SSL套接字

时间:2012-03-15 19:31:07

标签: c# java sockets authentication ssl

我正在尝试在.NET和Java之间创建SSL套接字服务器/客户端。在这种情况下,我的SSL套接字服务器将在.net中运行,客户端在Linux下以Java运行。我的问题是握手期间连接失败,特别是当服务器从客户端请求证书时,客户端无法发送回来的东西,连接失败。

在.net中我使用sslStream建立连接,在Java上我使用的是标准的SSLSocket。下面是一些代码片段,但这是我到目前为止所做的:

在服务器端(Windows),我在MMC下的Personal / Certificates文件夹中有一个私有证书。我在“受信任的人/证书”中拥有来自客户的公共证书。两个证书都是由同一个CA颁发的。两个证书的证书链都有多个级别,但两者都相同。链中的根级证书也安装在受信任的证书颁发机构/证书文件夹中。

在客户端(Linux)上,我有一个密钥库,其中包含与服务器上安装的公共证书相匹配的私有证书。我有一个信任存储,它包含来自服务器的公共证书,与服务器的私有证书匹配。

在服务器端(.net)我正在使用一个执行异步读取的Socket然后它被包装到一个SSLStream中,代码片段是这样的:

NetworkStream ns = new NetworkStream(socket, false);
SslStream ssl = new SslStream(ns, true);
ssl.AuthenticateAsServer(serverCertificate, true, SslProtocols.Default, true);

客户端代码几乎是标准代码:

SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
InetAddress addr = InetAddress.getByName(servername);
SSLSocket socket = (SSLSocket) factory.createSocket(addr,port);
socket.setUseClientMode(true);
socket.setNeedClientAuth(true);
socket.setWantClientAuth(true);
socket.startHandshake();
os = new DataOutputStream(socket.getOutputStream());
is = new DataInputStream(socket.getInputStream());
byte[] outBuf = new byte[50];
os.write("SEND SOMETHING".getBytes("UTF-8"));
is.read(outBuf);

在java中,我已经设置了正确的变量以指向信任和密钥存储区及其密码。

现在,按照标准的SSL握手,会发生以下情况:

  • 的ClientHello
  • 服务器问候
  • 服务器发送公共证书
  • 客户端将公共证书与信任存储上的证书相匹配
  • 服务器发送证书请求
  • 使用证书请求,服务器会发送有效CA列表,在此列表中仅发送我的根CA(在其他众所周知的CA的长列表中)。
  • 客户端证书为空。
  • 服务器从客户端收到空证书,从而关闭连接。

就是这样,客户端不会将有效证书发送回服务器。我对此有一些疑问:

有没有人经历过这样的事情? 关于服务器发送的CA列表(Windows),.net如何确定要发送给客户端的内容?有没有办法修改该列表? 我是否需要发送用于在CA列表中签署证书的链中的所有权限?或者根够了吗?

我的代码两边都遗漏了什么?

任何帮助将不胜感激。 在

1 个答案:

答案 0 :(得分:1)

以下两个陈述在客户端无用(尽管它们不应该受到伤害):

socket.setNeedClientAuth(true);
socket.setWantClientAuth(true);

您看到证书请求消息和客户端证书消息表明服务器配置正确。

客户端证书消息中缺少证书的最可能原因是密钥库(在客户端)可能未正确配置。您可能对this answer感兴趣,以确保正确配置了客户端密钥库。更具体地说,您需要确保将客户端证书的私钥导入到与证书链相同的别名中(并且它是返回到证书请求消息中公布的CA的链)。

(关于你的其他问题,我不确定在C#中使用SslStream时如何修改服务器发送的CA列表。This earlier question似乎表明没有解决方案,虽然问题的新版本.Net可能已经解决了这个问题。我通过查看SslStream API文档和相关类来找不到任何可以解决的问题。但这不是意味着它不存在。)