Создать экземпляр 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:
- Обычный DTLS/TLS и JSSE пакет поставщика
- FIPS-совместимый (D), TLS API, и 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());