簡體   English   中英

當密鑰庫有多個服務器證書時,Java 如何選擇默認證書

[英]How does Java pick default certificate when keystore has multiple server certificates

當客戶端根本沒有設置 SNI 服務器名時,Java 如何選擇默認/備用服務器證書?

背景:

我創建了具有多個服務器證書的 PKCS#12 密鑰庫。 我也用 JKS 密鑰庫進行了測試。 我使用NewSunX509X509KeyManager實現,它可以根據請求的 SNI 服務器名稱選擇匹配的服務器證書。

我找不到 JSSE 用來選擇默認或“回退”服務器證書的規則,當客戶端未在 TLS 握手中發送 SNI 服務器名時,它會返回該證書。 我沒有找到文檔或通過測試弄清楚。 實現( 代碼鏈接)說它對不完美的匹配進行排序。 在實踐中,選擇似乎受到在密鑰庫中添加條目的順序的影響,但它並不是簡單地選擇第一個或最后一個條目,或者按別名排序,即使代碼注釋給出了這種印象。

我沒有看到任何關於按別名排序的評論。 如果發生不完全匹配排序,它使用EntryStatus.compareTo ,它首先按CheckResult排序(即衡量證書與“好”的接近程度),然后是keyIndex ,它是它在基於調用者請求的keyTypes列表中的位置在 SSL/TLS 協議上(即 ciphersuite(s) 和/或 signature_algorithm 值,可能按優先順序排列)。 如果它們都相等,則Collections.sort是穩定的,因此它將使用它們被測試和找到的順序,請參閱下一個。

然而,排序只有在沒有“完美”匹配的情況下才會發生; 一旦找到任何“完美”匹配,它就會返回而不尋找任何可能存在的其他匹配。 因此,返回哪個取決於查看和測試密鑰庫條目的順序。 您鏈接的chooseAlias及其 with-SNI-idalg 兄弟,如果有多個,則首先按“builder”順序查看,通常不會有; 在“構建器”中(即在密鑰庫中),它們調用getAliases ,您可以看到它使用ks.aliases()返回的Enumeration ——這由使用的KeyStore實例確定。

像 PKCS12 和 JKS 這樣的基於文件的密鑰庫通常使用Map或以別名為鍵的舊(預收集) Hashtable表。 特別是 PKCS12 使用LinkedHashMap ,它按插入的順序返回密鑰/條目,我認為這或多或少是它們在存儲文件中存在的順序(盡管在 PKCS12 中,證書和私鑰的順序可能不同,我不確定哪些控件)但這不必與別名/名稱、創建或其他任何內容的順序相同。 JKS 使用Hashtable表,它以哈希碼的降序枚舉映射大小,映射大小主要取決於插入的條目數,並且在發生沖突的情況下,它使用鏈表並以插入的相反順序返回——除非可能重新散列改變了。

對於像 PKCS11、Windows、Apple 這樣的非基於文件的密鑰庫,它可以由 Java 接口代碼、底層工具提供的內容或組合來確定。

TLDR:就您而言,它是不可預測的,出於實際目的,它也可能是隨機的。 如果你關心你得到哪一個,要么編寫你自己的KeyManager邏輯來實現你的選擇(或使用像 Apache httpcomponents 這樣的預先編寫的邏輯),或者過濾你提供給默認 KeyManager 的密鑰庫中的數據。

另外要明確的是,這僅適用於您指定的NewSunX509 默認的 KeyManager 是(仍然!)較舊的SunX509 ,並且工作方式不同; 它有自己的HashMap 來控制迭代,而不是使用底層密鑰庫的。 (單數,因為 SunX509 只需要一個。)

暫無
暫無

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

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