«1. Обзор

В этом руководстве мы представим SSL и рассмотрим, как мы можем использовать его в Java с помощью API JSSE (Java Secure Socket Extension).

2. Введение

Проще говоря, Secured Socket Layer (SSL) обеспечивает защищенное соединение между двумя сторонами, обычно клиентами и серверами.

SSL обеспечивает безопасный канал между двумя устройствами, работающими через сетевое соединение. Одним из обычных примеров SSL является обеспечение безопасной связи между веб-браузерами и веб-серверами.

В этом конкретном случае веб-браузеры будут использовать соединения HTTPS (S означает защищенные) для доступа к ресурсам, предоставляемым отдельными веб-серверами.

SSL необходим для поддержки трех основных принципов информационной безопасности:

    Шифрование: защищает передачу данных между сторонами
    Аутентификация: гарантирует, что сервер, к которому мы подключаемся, действительно является надлежащим сервером запрошенные данные — это то, что эффективно доставляется
    Java предоставляет несколько API-интерфейсов, основанных на безопасности, которые помогают разработчикам устанавливать безопасные соединения с клиентом для получения и отправки сообщений в зашифрованном формате:

Java Secured-Socket Extension (JSSE) Java Криптографическая архитектура (JCA) Криптографическое расширение Java (JCE)

    В следующих разделах мы представим расширение защищенных сокетов, которое Java использует для обеспечения безопасной связи.

3. API JSSE

API безопасности Java широко используют шаблон проектирования Factory.

На самом деле все создается с помощью фабрики в JSSE.

3.1. SSLSocketFactory

Объект javax.net.ssl.SSLSocketFactory используется для создания объектов SSLSocket.

Этот класс содержит три группы API.

Первая группа состоит из одного статического метода getDefault(), используемого для получения экземпляра по умолчанию, который, в свою очередь, может создавать экземпляры SSLSocket.

Вторая группа состоит из пяти методов, которые можно использовать для создания экземпляров SSLSocket:

Socket createSocket(String host, int port) Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) Socket createSocket(InetAddress host, int port) Socket createSocket(InetAddress host, int port, InetAddress clientHost, int clientPort) Socket createSocket(Socket socket, String host, int port, boolean autoClose)

    Мы можем использовать этот класс напрямую, получив экземпляр по умолчанию или с помощью объекта javax.net.ssl.SSLContext, который содержит методы для получения экземпляра SSLSocketFactory.

3.2. SSLSocket

Этот класс расширяет класс Socket и обеспечивает безопасный сокет. Такие сокеты являются обычными потоковыми сокетами.

Кроме того, они добавляют уровень защиты к основному сетевому транспортному протоколу.

Экземпляры SSLSocket создают SSL-соединение с именованным хостом на указанном порту.

Это позволяет привязать клиентскую сторону соединения к заданному адресу и порту.

3.3. SSLServerSocketFactory

Класс SSLServerSocketFactory очень похож на SSLSocketFactory с той разницей, что он создает экземпляры SSLServerSocket вместо экземпляров SSLSocket.

По сходству методы называются createServerSocket по аналогии с классом SSLSocketFactory.

3.4. SSLServerSocket

Класс SSLServerSocket аналогичен классу SSLSocket. Методы класса SSLServerSocket являются подмножеством методов класса SSLSocket. Они действуют на противоположной стороне соединения SSL

4. Пример SSL

Давайте представим пример того, как мы можем создать защищенное соединение с сервером:

В случае, если мы получим ошибку †«javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: Ошибка построения пути PKIX: sun.security.provider.certpath.SunCertPathBuilderException: невозможно найти допустимый путь сертификации к запрошенному целевому объекту при установлении SSL-соединения», это указывает на то, что у нас нет общедоступного сертификата сервера, к которому мы пытаемся подключиться в хранилище доверенных сертификатов Java.

String host = getHost(...);
Integer port = getPort(...);
SSLSocketFactory sslsocketfactory = SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory
  .createSocket(host, port);
InputStream in = sslsocket.getInputStream();
OutputStream out = sslsocket.getOutputStream();

out.write(1);
while (in.available() > 0) {
    System.out.print(in.read());
}

System.out.println("Secured connection performed successfully");

Хранилище доверенных сертификатов — это файл, содержащий доверенные сертификаты, которые Java использует для проверки защищенных соединений.

«Чтобы решить эту проблему, у нас есть несколько вариантов:

добавить общедоступный сертификат сервера в хранилище доверенных сертификатов cacerts по умолчанию, используемое Java. при инициировании соединения SSL Установите переменную среды javax.net.ssl.trustStore так, чтобы она указывала на файл хранилища доверенных сертификатов, чтобы приложение могло подобрать этот файл, содержащий общедоступный сертификат сервера, к которому мы подключаемся.

    Шаги для установки нового сертификата в хранилище доверенных сертификатов Java по умолчанию:

После того, как мы это сделали, мы сможем снова запустить пример и получить сообщение «Защищенное соединение выполнено успешно».

  1. extract cert from server: openssl s_client -connect server:443
  2. import certificate into truststore using keytool: keytool -import -alias alias.server.com -keystore $JAVA_HOME/jre/lib/security/cacerts

5. Заключение

В этой статье мы представили SSL и JSSE API, который реализует SSL для Java. Используя SSL и JSSE, мы можем сделать наши Java-приложения и обмен данными между приложениями и внутри приложения более безопасными.

Как всегда, код, представленный в этой статье, доступен на Github.

«