Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java SSL服务器不接受中间证书链_Java_Ssl_Netty - Fatal编程技术网

Java SSL服务器不接受中间证书链

Java SSL服务器不接受中间证书链,java,ssl,netty,Java,Ssl,Netty,我已经实现了一个(Netty 3.6.6,Java 6)服务器,它接受SSL/TLS连接,并且需要对客户端的证书链进行身份验证。我的信任商店里有普通的CA。除了这里描述的情况外,服务器的SSL实现基本上可以工作。如果有有效的签名证书(用于连接到其他服务器),我可以通过以下方式成功连接到我的服务器: openssl s_client -connect 127.0.0.1 -key test.key -cert test.pem -CAfile capath.pem 但是,如果证书和中间产品连接在

我已经实现了一个(Netty 3.6.6,Java 6)服务器,它接受SSL/TLS连接,并且需要对客户端的证书链进行身份验证。我的信任商店里有普通的CA。除了这里描述的情况外,服务器的SSL实现基本上可以工作。如果有有效的签名证书(用于连接到其他服务器),我可以通过以下方式成功连接到我的服务器:

openssl s_client -connect 127.0.0.1 -key test.key -cert test.pem -CAfile capath.pem
但是,如果证书和中间产品连接在一起,并且我连接到:

openssl s_client -connect 127.0.0.1 -key test.key -cert all.pem
然后抛出
无法找到请求目标的有效认证路径;我希望这种方法能奏效

我的代码是(缩写):

我做错了什么?我们的客户报告说,这种行为与他们使用的其他服务器不同,所以我不希望这会给他们带来问题;这合理吗?(大量的谷歌搜索没有帮助…)


谢谢:-)

你的期望是错误的
openssl s_客户端-证书文件
仅使用第一个证书,该证书必须是客户端证书。在该文件中放置其他证书(链或其他证书)将被忽略。因此,
s_客户端
(通过libssl客户端)发送一个不完整的链。通常情况下,服务器无法对此进行验证

尽管
-CAfile
和/或
-CAdir
被记录为为
s_客户端提供根以验证对等(服务器)证书,但libssl还使用信任库填写其发送的链(如果必要和可能);显然,您在
cacert.pem
中有您的连锁证书,并且发生了这种情况

我假设您的客户没有使用
s_client
,因为它发送和接收合适数据的能力非常有限。 如果您或其他人使用libssl编写或编写了一个真实的应用程序,您可以通过调用
SSL\u CTX\u use\u certificate\u chain\u file
而不是
SSL\u CTX\u use\u certificate\u file
来设置(整个)链,或者您可以使用
SSL\u CTX\u add\u extra\u chain\u cert>从单个证书构建链。(如果只有一种中间语言,它们实际上是等效的。)更不用说在Java、perl和dotNET等其他语言中可以做什么了
s_客户端
被设计为一个测试和调试工具,不做这些;它只使用只使用第一个证书的证书

警告:这是OpenSSL到1.0.1的全部内容。1.0.2现在beta版发布了证书和链验证的更改,我还没有检查过。尽管基于过去的实践,我自信地预期默认值将继续保持在早期版本中


如果您确实需要Java服务器来接受发送不完整链的客户机(根据RFC,它不需要这样做),那么您可以将第一个未发送的中间段(这里是第一个中间段)放在服务器信任库中。但我相信(不容易测试)在这种情况下,Java将完全忽略链的其余部分,因此您必须手动或通过其他方式进行监控,例如撤销。

谢谢。openssl命令是同事用来测试服务器的,并为用户提供足够的线索,以便他们修复(未知)实现。我现在意识到这些可能是不同的问题。如果没有用户的实现,我不能确定我能重现他们的确切问题;考虑到它们与其他服务器的连接良好,要么我们在某个地方有一个bug,要么其他服务器不那么严格。棘手的谢谢你的帮助。为什么你认为Java会忽略链的其余部分?它必须通过链建立从实际客户端证书到信任库中证书的路径。这是如何构成忽略的?@EJP如果实际链是SheepMolly/Shepherd1/WoollyRoot,并且您将Shepherd1放在信任库中(因为不遵从的对等方只发送SheepMolly),那么看起来Java将构建SheepMolly-Shepherd1链,并在那里停止,因为Shepherd1是受信任的,至少根据
握手完成事件.getPeerCertificates
。但实际上,Shepherd1可能已被撤销,查看完整链的relier会检测到这一点。@Liche如果您无法查看客户端,您是否可以使用Wireshark或等效工具在您的服务器或至少服务器的网段上捕获它们的连接?这样就很容易弄清楚他们到底在发送什么;如果它能起作用,那么你就有明确的事情要解决,如果不能,你可以告诉他们要解决什么。获得在生产敏感网络上捕获的许可有时是一个问题;如果您可以让该客户机连接到您设置的测试服务器,这通常会更容易。。。。。。或者,更糟糕的是,从获取权限的因素来看,您可以使用sysprop
javax.net.debug
在JSSE中打开非常详细的日志记录。但是你必须在很多垃圾中跋涉才能找到好的部分,你不能像Wireshark那样点击。
public class MySslConnectionHandler extends FrameDecoder {
    // this class is added into the netty ChannelPipeline (not shown)

    private SSLContext sslContext;

    public MySslConnectionHandler() {
        KeyStore clientKeyStore = KeyStore.getInstance('JKS');
        clientKeyStore.load(new FileInputStream(trustStoreFilename), trustStorePassword);

        PKIXSSLContextFactory contextFactory = new PKIXSSLContextFactory(serverKeyStore, keyStorePassword, clientKeyStore, true);

        this.sslContext = contextFactory.buildSSLContext();
    }

    @Override
    protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
        SSLEngine engine = sslContext.createSSLEngine();
        engine.setUseClientMode(false);
        engine.setNeedClientAuth(true);
        engine.setEnabledProtocols(new String[] {"TLSv1","SSLv3"});

        SslHandler sslHandler = new SslHandler(engine);
        sslHandler.setEnableRenegotiation(false);

        ChannelFuture handshakeFuture = sslHandler.handshake();
        handshakeFuture.addListener(new MySslHandshakeListener(engine));

        return buffer.readBytes(buffer.readableBytes());
    }
}