Создать экземпляр SSLContext с помощью поставщика Bouncy Castle

Я застрял в создании SSLContext (который я хочу использовать для создания экземпляра SSLEngine для обработки зашифрованного транспорта через java-nio):

Код

String protocol = "TLSv1.2";
Provider provider = new BouncyCastleProvider();
Security.addProvider(provider);
sslContext = SSLContext.getInstance(protocol,provider.getName());

выдает следующее исключение:

Exception in thread "main" java.lang.RuntimeException: java.security.NoSuchAlgorithmException: no such algorithm: SSL for provider BC
at org.bitmash.network.tcp.ssl.SslTransferFactory.<init>(SslTransferFactory.java:43)
at org.bitmash.network.http.HttpsServer.<init>(HttpsServer.java:19)

Я подключил текущий пакет поставщика Bouncy Castle 'bcprov-jdk15on-150.jar' (который я получил здесь) к пути к классам приложений, а также к его пути к загрузочному классу (через VM-Option -Xbootclasspath/p), но ни одна из них не решила проблему. Я также пробовал разные значения для protocol (то есть "SSL" и "TLSv1") без какого-либо эффекта.

Кроме того, я нашел людей с похожими проблемами здесь и здесь. Но в отличие от них, я нацеливаюсь (и использую) Java 7 (или выше), но у меня все еще есть эта проблема. Можно ли вообще использовать Bouncy Castle таким образом, или мне нужно переписать мой протокол, используя соответствующий API вместо NIO оракула через SSLEngine (как я сейчас это делаю)?

Большое спасибо за любую помощь здесь.

2 ответа

Решение

Я знаю, что это довольно старый вопрос, но мне нужен был ответ (поэтому я его создаю):

  • [Можно ли] создать экземпляр SSLContext с помощью поставщика Bouncy Castle [?]
  • нет

Почему бы и нет?

Отладка этой строки кода:

Provider [] providers = Security.getProviders();
  • в SunJSSE версии 1.7 по умолчанию реализованы следующие значения SSLContext:

    Alg.Alias.SSLContext.SSL = TLSv1
    Alg.Alias.SSLContext.SSLv3 = TLSv1
    SSLContext.Default = sun.security.ssl.SSLContextImpl $ DefaultSSLContext
    SSLContext.TLSv1 = sun.security.ssl.SSLContextImpl $ TLS10Context
    SSLContext.TLSv1.1 = sun.security.ssl.SSLContextImpl $ TLS11Context
    SSLContext.TLSv1.2 = sun.security.ssl.SSLContextImpl $ TLS12Context

  • Используя bcprov-jdk15on-152.jar и добавляя новый BouncyCastleProvider() в Security, можно заметить, что нет доступных значений SSLContext.

Это должно иметь смысл, поскольку Bouncy Castle - это реализация JCE, а не реализация JSSE.

На самом деле Bouncy Castle предоставляет реализацию JSSE начиная с версии 1.56. Просто убедитесь, что он настроен с более высоким приоритетом в java.security:

security.provider.1=org.bouncycastle.jsse.provider.BouncyCastleJsseProvider
...
security.provider.6=com.sun.net.ssl.internal.ssl.Provider

Вы можете использовать его тогда со стандартным API:

SSLContext context = SSLContext.getInstance("TLS");

Bouncy Castle реализует два типа провайдеров для JSSE:

Здесь можно найти актуальную документацию для каждого провайдера: обычную и совместимую с FIPS.

Файлы JAR для них отличаются от файла JAR для провайдера Bouncy Castle JCE. На момент написания JAR-файлы поставщика JSSE называлисьbctls-jdk15on-1.64.jar а также bctls-fips-1.0.9.jar, а провайдер JCE - bcprov-jdk15on-1.64.jar.

Вот выдержка из документации:

2.1 Установка поставщика BCJSSE в JRE

После установки bctls jar может потребоваться установить класс поставщика BouncyCastleJsseProvider, если он требуется в приложении глобально.

Установку поставщика можно выполнить статически в JVM, добавив его в определение поставщика в java.security файл в jre/lib/security каталог для вашего JRE/JDK.

Поставщик также может быть добавлен во время выполнения. Если вы хотите добавить поставщика в JVM глобально во время выполнения, вы можете добавить в свой код следующие операции импорта:

import java.security.Security
import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider

Затем вставьте строку

Security.addProvider(new BouncyCastleJsseProvider());

Затем можно использовать поставщика, указав имя BCJSSE, например:

SSLContext clientContext = SSLContext.getInstance("TLS", "BCJSSE");

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

Например:

SSLContext clientContext = SSLContext.getInstance("TLS",
       new BouncyCastleJsseProvider());
Другие вопросы по тегам