tls 使用java生成_同时使用传入和传出连接时,相互TLS身份验证存在Java问题
tls 使用java生成
在大多數企業環境中,應用程序之間的連接中使用某種形式的安全通信(例如TLS或SSL)。 在某些環境中, 相互(雙向)身份驗證也是一項非功能性要求。 有時將其稱為雙向SSL或雙向TLS身份驗證。 因此,除了提供證書的服務器外,它還請求客戶端發送其證書,以便隨后可以使用它來驗證調用方。
我當前客戶的一個合作伙伴正在開發一種服務器,該服務器可以通過MQTT接收數據,并且由于數據非常敏感,因此客戶決定應使用相互TLS身份驗證來保護數據。 此外,客戶要求將該服務器收集的聚合數據發布到其他下游服務時,還必須使用雙向TLS身份驗證來完成。 該服務器需要向其調用方提供服務器證書,以便他們可以驗證主機名和身份,但是,當在SSL握手期間被請求這樣做時,它還必須向下游服務器提供具有有效用戶ID的客戶端證書。
最初的想法是使用用于配置密鑰庫的標準JVM系統屬性來實現此目的:“-Djavax.net.ssl.keyStore =…”,即將客戶端和服務器證書都放入單個密鑰庫中。 但是,我們很快意識到這是行不通的,并且跟蹤SSL調試日志表明,無論是在傳入SSL握手期間還是傳出SSL握手期間,服務器都提供了錯誤的證書。 在傳入握手期間,它應出示其服務器證書。 在外發握手期間,應出示其客戶證書。
注釋了以下日志摘錄,并顯示了這些問題:
- 出示給呼叫者的證書錯誤
- 向下游提交了錯誤的證書
經過進一步調查,很明顯該問題與JVM中的默認密鑰管理器實現有關。 的
SunX509KeyManagerImpl類用于選擇JVM在握手期間應提供的證書,并且對于客戶機證書和服務器證書選擇,代碼僅采用它找到的第一個證書:
第一行中的方法返回的別名僅匹配密鑰類型(例如DSA)和可選的頒發者。 因此,在密鑰庫包含兩個或多個證書的情況下,選擇性不夠。 此外,列表的順序基于對HashMap條目集的迭代,因此順序不是說字母順序的,而是確定性的和恒定的。 因此,在搜索服務器證書時,該算法可能會返回客戶端證書。 但是,如果該部分起作用,則當服務器進行下游連接并需要出示其客戶端證書時,該算法將失敗,因為將再次出示第一個證書,即服務器證書。 因此,由于不可能創建并發的傳入和傳出雙向SSL連接,因此我向Oracle提交了一個錯誤(內部審查ID 9052786在20180225上報告給Oracle)。
一種解決方案是使用兩個密鑰庫,每個證書存儲一個, 如此處所示 。
JVM的一個可能補丁是通過使用
“擴展密鑰用法”證書擴展。 基本上,可以增強上述代碼,以額外檢查擴展的密鑰用法并在選擇別名時做出更明智的決定,例如:
選擇別名的方法如下:
private String selectAliasBasedOnExtendedKeyUsage(String[] aliases, String targetExtendedKeyUsage) {for(String alias : aliases){//assume cert in index 0 is the lowest one in the chain, and check its EKUX509Certificate certificate = this.credentialsMap.get(alias).certificates[0];List ekus = certificate.getExtendedKeyUsage();for (String eku : ekus) {if(eku.equals(targetExtendedKeyUsage)){return alias;}}}return null; }更多詳細信息,包括完整運行的示例和單元測試, 請參見此處 。
翻譯自: https://www.javacodegeeks.com/2018/03/java-problem-with-mutual-tls-authentication-when-using-incoming-and-outgoing-connections-simultaneously.html
tls 使用java生成
總結
以上是生活随笔為你收集整理的tls 使用java生成_同时使用传入和传出连接时,相互TLS身份验证存在Java问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何申请域名网址(如何申请域名)
- 下一篇: java美元兑换,(Java实现) 美元