Я пытаюсь создать сокет-сервер / клиент SSL между .NET и Java.В этом случае мой сервер SSL Socket Server будет работать в .net, а клиент работает на Java под Linux.Моя проблема заключается в том, что во время установления соединения происходит сбой соединения, в частности, когда сервер запрашивает сертификат у клиента, клиент не может отправить что-либо обратно, и соединение не устанавливается.
В .net Я использую sslStream для установкисоединение и на Java я использую стандартный SSLSocket.Ниже приведены некоторые фрагменты кода, но это то, что у меня пока есть:
На стороне сервера (Windows) у меня есть личный сертификат в папках Personal / Certificates в MMC.У меня есть открытый сертификат от клиента в доверенных лиц / сертификаты.Оба сертификата были выданы одним и тем же центром сертификации.Цепочка сертификатов для обоих сертификатов имеет несколько уровней, но она одинакова для обоих.Сертификат корневого уровня в цепочке также установлен в папке доверенных центров сертификации / сертификатов.
На стороне клиента (Linux) у меня есть хранилище ключей, которое содержит частный сертификат, соответствующий общедоступному сертификату, установленному насервер.У меня есть хранилище доверенных сертификатов, которое содержит общедоступный сертификат сервера, совпадающий с частным сертификатом сервера.
На стороне сервера (.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 я установил правильные varialbes, чтобы указывать на довериеи хранилище ключей с их паролем.
Теперь, после стандартного SSL Handshake, вот что происходит:
- ClientHello
- ServerHello
- Serverотправляет открытый сертификат
- Клиент сопоставляет открытый сертификат с сертификатом, хранящимся в доверенном хранилище
- Сервер отправляет запрос сертификата
- При запросе сертификата сервер отправляет список действительных центров сертификации., в этом списке отправляется только мой корневой ЦС (среди длинных списков других известных ЦС.).
- Сертификат клиента равен нулю.
- Сервер получает нулевое значениеЯ получу сертификат от клиента, тем самым закрою соединение.
И все, клиент не отправит действительный сертификат обратно на сервер.У меня есть несколько вопросов по этому поводу:
Кто-нибудь испытывал что-то подобное?Что касается списка CA, отправленного сервером (Windows), как .net определяет, что отправить клиенту?Есть ли способ изменить этот список?Нужно ли отправлять все полномочия в цепочке, которые использовались для подписи моего сертификата в этом списке центров сертификации?или Root достаточно?
Я что-то упустил по обе стороны моего кода?
Любая помощь будет принята с благодарностью.В