Инициализация SSLContext

Я смотрю справочное руководство JSSE, мне нужно получить экземпляр SSLContext, чтобы создать SSLEngine, поэтому я могу использовать его с Netty для включения безопасности.

Чтобы получить экземпляр SSLContext, я использую SSLContext.getInstance(). Я вижу, что метод переопределяется несколько раз, поэтому я могу выбрать протокол и поставщика безопасности для использования.

Здесь, я вижу список алгоритмов, которые можно использовать. Какой алгоритм я должен использовать для обеспечения безопасной связи?

Кроме того, поскольку можно указать поставщика безопасности для использования, какой провайдер должен использовать?

Спасибо

Ответ 1

Как вы можете видеть в документации стандартных имен, все записи (SSLv3, TLSv1.0, TLSv1.1,...) говорят что они могут поддерживать другие версии.

На практике в Oracle JDK (и OpenJDK) они все делают. Если вы посмотрите на исходный код, класс TLS10Context используется для TLS, SSL, SSLv3 и TLS10, TLS11Context используется для TLSv1.1 и TLS12Context для TLSv1.2. Все поддерживают все версии SSL/TLS, это зависит от того, что включено по умолчанию.

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

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

Как правило, используйте наивысший номер версии (SSLv3 < TLSv1.0 < TLSv1.1...), который может зависеть от того, с какими сторонами вы хотите поддерживать связь.


Какие протоколы включены по умолчанию, зависит от конкретной версии Oracle JRE.

При просмотре исходного кода для sun.security.ssl.SunJSSE в OpenJDK 7u40-b43, TLS является просто псевдонимом для TLSv1 ( а также SSL и SSLv3) в терминах протоколов SSLContext. Рассматривая различные реализации SSLContextImpl (которые являются внутренними классами самого SSLContextImpl):

  • Все поддерживают все протоколы.
  • По умолчанию все протоколы включены на стороне сервера.
  • поддерживаемые по умолчанию протоколы на стороне клиента различаются:
    • TLS10Context (используется для протокола SSL, SSLv3, TLS, TLSv1) позволяет SSLv3 по TLSv1.0 по умолчанию на стороне клиента.
    • TLS11Context (используется для протокола TLSv1.1) также включает TLSv1.1 по умолчанию.
    • TLS12Context (используется для протокола TLSv1.2) также включает TLSv1.2 по умолчанию.
  • Если FIPS включен, SSL не поддерживается (по умолчанию он не включен).

Это изменение в Java 8 в сочетании с новым системным свойством jdk.tls.client.protocols.

Опять же, при просмотре исходного кода для sun.security.ssl.SunJSSE в OpenJDK 8u40-b25, SSLContext протоколов TLSv1, TLSv1.1 и TLSv1.2 также используют TLS10Context, TLS11Context и TLS12Context, которые следуют той же логике, что и в Java 7.

Однако протокол TLS уже не является псевдонимом для любого из них. Скорее, он использует TLSContext, который опирается на значения в системных свойствах jdk.tls.client.protocols. Из Справочное руководство JSSE:

Чтобы включить определенные клики SunJSSE на клиенте, укажите их в списке, разделенном запятыми, в кавычках; все остальные поддерживаемые протоколы затем отключены на клиенте. Например, если значением этого свойства является "TLSv1, TLSv1.1", то на клиенте будут установлены параметры протокола по умолчанию для TLSv1 и TLSv1.1, тогда как SSLv3, TLSv1.2 и SSLv2Hello отключены на клиент.

Если это свойство пустое, все протоколы включены по умолчанию как на стороне клиента, так и на стороне сервера.

Конечно, в последних версиях Oracle JRE 8 SSL по умолчанию полностью отключен (поэтому удалено из этих списков).

Обратите внимание, что в обоих случаях (JRE 7 и 8) SSLContext, который вы получаете по умолчанию через SSLContext.getDefault() из коробки, более или менее эквивалентен SSLContext, полученному с протоколом TLS, и инициализируется с помощью параметры доверия по умолчанию и т.д.

Ответ 2

По умолчанию для протокола нет значения, поэтому я бы использовал последний, поддерживаемый вашим JDK, который является либо TLSv1, TLSv1.1, либо TLSv1.2: см., что работает, или посмотрите getSupportedProtocols(). Поставщик безопасности по умолчанию используется, избегая всех API-интерфейсов, где вы его указываете, или, например, KeyStore.getDefaultType().

И когда вы придете, чтобы получить свои SSLEngines, убедитесь, что вы используете метод, который принимает имя хоста и порт. В противном случае вы не получите сеанса сеанса SSL.