Я использую Netty 4.1.25.Я создаю X509Certificate
из pem
файла в моем коде.Используя этот сертификат, я настраиваю SslHandler следующим образом:
SslContext context = SslContextBuilder.forClient().trustManager( certificate ).build();
pipeline.addLast( "ssl", context.newHandler( socketChannel.alloc() ) );
Когда сертификат является точным сертификатом, который находится на сервере (сервер является устройством IoT, но, вероятно, не имеет значения), это работает нормально.
Однако, когда я создаю собственный корневой сертификат и:
- сервер имеет сертификат, который доверяет корневому сертификату
- приложение Netty использует корневой сертификат
Затем я получаю это исключение:
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:459) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:265) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:647) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysPlain(NioEventLoop.java:547) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:501) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:461) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:128) ~[na:na]
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:321) ~[na:na]
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:264) ~[na:na]
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:259) ~[na:na]
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:642) ~[na:na]
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:461) ~[na:na]
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:361) ~[na:na]
at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392) ~[na:na]
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:444) ~[na:na]
at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1065) ~[na:na]
at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1052) ~[na:na]
at java.base/java.security.AccessController.doPrivileged(Native Method) ~[na:na]
at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask.run(SSLEngineImpl.java:999) ~[na:na]
at io.netty.handler.ssl.SslHandler.runDelegatedTasks(SslHandler.java:1435) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1343) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1177) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1221) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:489) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:428) ~[netty-all-4.1.25.Final.jar:4.1.25.Final]
... 16 common frames omitted
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:385) ~[na:na]
at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:290) ~[na:na]
at java.base/sun.security.validator.Validator.validate(Validator.java:264) ~[na:na]
at java.base/sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:321) ~[na:na]
at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:279) ~[na:na]
at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:141) ~[na:na]
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:620) ~[na:na]
... 30 common frames omitted
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141) ~[na:na]
at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126) ~[na:na]
at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297) ~[na:na]
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380) ~[na:na]
... 36 common frames omitted
Для тестирования я также использовал опцию SslContextBuilder для использования TrustManagerFactory
вместо сертификата напрямую:
TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
factory.init(certificateService.getKeyStore());
SslContext context = SslContextBuilder.forClient().trustManager(factory).build();
Это, однако, создает ту же проблему.
Интересно, что это устройство IoT также имеет веб-интерфейс, который использует тот же сертификат.Когда я открываю этот URL, используя тот же TrustManagerFactory
, это работает без проблем:
SSLContext sc = SSLContext.getInstance("TLSv1.2");
sc.init(null, factory.getTrustManagers(), new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
URL url = new URL("https://10.65.101.155");
HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();
Используя urlConnection
, я могу распечатать содержимое веб-страницы и просмотреть информацию о сертификате.
Я уже работал с -Djava.security.debug=all
, но мне кажется, что это большая информация, которую я не совсем понимаю, я боюсь.
Почему это работает через URL
, но не через Netty, использующий то же самое?TrustManagerFactory
?Могу ли я что-нибудь сделать на стороне Netty для дальнейшей отладки этого?Есть ли возможность распечатать сертификат, который Netty получает от сервера?