当客户端根本没有设置SNI servername时,Java如何 Select 默认/回退服务器证书?

背景:

我用multiple server certificates创建了PKCS#12密钥库.我还使用JKS密钥库进行了测试.我使用X509KeyManagerNewSunX509实现,它可以根据请求的SNI服务器名 Select 匹配的服务器证书.

我找不到JSSE用于 Select 默认或"回退"服务器证书的规则,当客户端在TLS握手中不发送SNI servername时,JSSE将返回该规则.我没有找到文档,也没有通过测试找到答案.实现(code link)表示它对不完美匹配进行排序.实际上, Select 似乎会受到在keystore中添加条目的顺序的影响,但它不会简单地 Select 第一个或最后一个条目,也不会按别名排序,即使代码注释会给人留下这样的印象.

推荐答案

我没有看到任何关于按别名排序的 comments .If不完全匹配排序发生时,它使用EntryStatus.compareTo进行排序,首先是CheckResult(即,证书接近"良好"程度的度量),然后是keyIndex,这是调用者基于SSL/TLS协议请求的keyTypes列表中的位置(即密码套件和/或signature\u算法值,可能是优先顺序).如果两者相等,则Collections.sort是稳定的,因此它将使用测试和发现的顺序,请参阅下一步.

然而,只有当没有"完美"匹配时,才会进行排序;一旦找到任何"完美"匹配,就会返回,而不会寻找可能存在的任何其他匹配.因此,返回哪个取决于查看和测试密钥库条目的顺序.chooseAlias正如你所链接的,它与SNI idalg的sibling 姐妹一样,如果有多个,首先按"构建者"顺序查看,通常不会有;在"构建器"(即密钥库)中,他们调用getAliases,您可以看到,getAliases使用ks.aliases()返回的Enumeration,这由使用的KeyStore个实例决定.

File-based密钥库(如PKCS12和JKS)通常使用由alias键入的Map或更旧的(预集合)Hashtable.尤其是PKCS12使用LinkedHashMap,它以插入的顺序返回密钥/条目,我认为这或多或少就是它们在存储文件中的顺序(虽然在PKCS12中,证书和私钥的顺序可能不同,我不确定是哪个控件),但这不必与别名/名称、创建或其他任何东西的顺序相同.JKS使用Hashtable,它按哈希代码的降序对映射大小进行模化枚举,映射大小主要取决于插入的条目数,如果发生冲突,它将使用链表并按插入的相反顺序返回,除非重新灰化会改变这一点.

对于PKCS11、Windows、Apple等非基于文件的密钥库,可以通过Java接口代码、底层工具提供的内容或组合来确定.

TLDR:就你而言,这是不可预测的,实际上也可能是随机的.如果您关心您得到的是哪一个,可以编写自己的KeyManager逻辑来实现您的 Select (或者使用预先编写的逻辑,如Apache httpcomponents),或者过滤您提供给默认KeyManager的密钥库中的数据.

同样需要明确的是,这仅适用于您指定的NewSunX509.default键管理器(仍然!)更老的SunX509和工作方式不同;它有own个HashMap来控制迭代,而不是使用底层keystore的HashMap.(单数,因为SunX509只取一个.)

Java相关问答推荐

是否在允许数组元素为空时阻止 idea 为空性警告?

使用REST客户端和对象映射器从字符串反序列化Json

我正在try 跟踪数组中最大的两个数字

我如何知道MediaDiscoverer何时完成发现介质?

Javadoc在方法摘要中省略方法

迁移到Java 17后,日期显示不准确

如何集成语义发布和BitBucket(Java项目)

无法将GSON导入到我的JavaFX Maven项目

在java中使用不同的application.properties-jar而不使用Spring

在缺少字段时使用Jackson With Options生成Optional.Empty()

在Java中将.GRF转换为图像文件

具有多个分析模式的复杂分隔字符串的正则表达式

Maven创建带有特定类的Spring Boot jar和普通jar

如何转换Vector<;对象>;转换为int?

在外部类和内部类之间,当调用外部类内部或外部的主方法时,它们的静态初始化程序的运行顺序不同

单例模式中热切初始化和惰性初始化的区别

BigDecimal stripTrailingZeros 和相等

设置 JavaFx ScrollPane 值并不反映特定场景中的变化

为什么第二个方法调用会导致java崩溃?

代号一:Android 构建中找不到资源