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

标签 c# java sockets authentication ssl

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

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

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

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

在服务器端 (.net),我使用的是一个进行异步读取的套接字,然后它被包装到一个 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 中,我已经设置了正确的变量以使用密码指向信任和 keystore 。

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

  • 客户问候
  • 服务器问候
  • 服务器发送公共(public)证书
  • 客户端将公共(public)证书与信任库中的证书进行匹配
  • 服务器发送证书请求
  • 通过证书请求,服务器发送有效 CA 列表,在此列表中仅发送我的根 CA(在其他知名 CA 的长列表中)。
  • 客户端证书为空。
  • 服务器从客户端收到一个空证书,从而关闭连接。

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

有人遇到过这样的事情吗? 关于服务器发送的 CA 列表 (Windows),.net 如何确定要发送给客户端的内容?有没有办法修改该列表? 我是否需要发送用于在该 CA 列表中签署我的证书的链中的所有授权机构?还是 Root 就足够了?

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

任何帮助将不胜感激。 在

最佳答案

以下两个语句在客户端是无用的(尽管它们不应该造成伤害):

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

您看到 Certificate Request 消息和 Client Certificate 消息表明服务器配置正确。

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

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

关于c# - 带有客户端身份验证的 .Net 和 Java 之间的 SSL 套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9726802/

相关文章:

c# - 禁用键盘输入到 ASP 文本框

c# - 更新现有目录 - Apache-POI |开发工具包 |其他接口(interface)

c# - MySql Connector 6.8.2 RC、Entity Framework 6 和 Code First

java - java中的模拟

sockets - 未创建 uwsgi 套接字

c# - C#使用SoundPlayer同时播放多种声音

java - 为什么在数据库中插入JPA null

带有自己提示符的 Java 命令行应用程序

c - BIO_reset是否在内部调用close(socket_fd)?或者我们是否显式关闭套接字文件描述符

c# - 如何检查 TcpClient 连接是否关闭?