簡體   English   中英

Java SSL服務器不接受中間證書鏈

[英]Java SSL server not accepting intermediate certificate chain

我已經實現了一個(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

然后我unable to find valid certification path to requested target拋出unable to find valid certification path to requested target 我希望這種方法行得通。

我的代碼是(縮寫):

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());
    }
}

我究竟做錯了什么? 我們的客戶報告說,這種行為不同於他們使用的其他服務器,因此,我不希望這導致他們出現問題。 這合理嗎? (廣泛的谷歌搜索沒有幫助...)

謝謝 :-)

您的期望是錯誤的。 openssl s_client -cert file 僅使用第一個證書 ,該證書必須是客戶端證書。 在該文件中放置其他證書,鏈或其他證書將被忽略。 結果, s_client (通過libssl客戶端)發送了不完整的鏈。 通常,服務器無法對此進行驗證。

盡管-CAfile和/或-CAdir被記錄為s_client提供根以驗證對 (服務器)證書,但libssl 還在必要和可能的情況下使用信任庫來填充它發送的鏈。 顯然,您在cacert.pem擁有您的連鎖證書,並且這發生了。

我假設您的客戶沒有使用s_client因為它發送和接收合適數據的能力非常有限。 如果你或寫或使用的libssl寫一個真正的應用程序,你可以通過調用設置(全)鏈SSL_CTX_use_certificate_chain_file代替SSL_CTX_use_certificate_file也可以構建從個人證書鏈SSL_CTX_add_extra_chain_cert (如果您只有一個中間件,那么它們實際上是等效的。)更不用說您可以使用其他語言(例如Java,perl和dotNET)進行操作。 s_client被設計為測試和調試工具,並且不執行這些操作; 僅使用僅使用第一個證書的use_certificate

告誡:以上全部針對OpenSSL 1.0.1。 Beta版本1.0.2現已宣布,我尚未檢查的證書和鏈驗證已發生更改。 盡管基於過去的實踐,但我有信心地期望默認值將繼續與早期版本相同。

如果您確實需要Java服務器來接受發送不完整鏈的客戶端(根據RFC,它不需要這樣做),則可以將未發送的第一個中間節點(這里是第一個中間階段)放入服務器信任庫中。 但我相信在這種情況下(無法輕松測試),Java將完全忽略該鏈的其余部分,因此您將必須手動或通過某種其他方式進行監視(例如吊銷)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM