我正在运行JVM参数中配置的Java进程(微服务)和trustStore。如果微服务需要连接外部 URL,需要在 trustStore 中导入证书。
Example:
example.co.uk -> examplecouk as alias in trustStore
example.com -> examplecom as alias in trustStore
example.in -> examplein as alias in trustStore
Java 如何知道要从 trustStore 中为特定端点选择哪些证书和别名,因为我没有在 JVM 参数中传递/提及别名?是随机挑选的吗?
user207421 几乎是正确的。更准确地说:
当您作为客户端打开与服务器的 SSL/TLS 连接时,作为握手的一部分,服务器发送其证书“链”,其中包含自己的证书,通常还有一个或多个链接的 CA(证书颁发机构)证书以“根”结尾' 应该信任的 CA。请参阅相邻的 Stack https://security.stackexchange.com/questions/20803/how-does-ssl-work/ 以获得史诗般的完整解释。公共服务器通常使用由 Digicert、GoDaddy、LetsEncrypt/ISRG 等公共 CA 颁发和签名的证书,这些证书已经在标准默认信任库中(对于文件
JRE/lib/security/cacerts
中的 Java),因此无需采取任何措施。如果服务器使用来自非品牌或私有 CA 的证书,或自签名证书(根本没有来自任何 CA),则(对于 Java)必须将链中的some 证书添加到客户端信任库,或者否则被覆盖;在服务器证书是自签名的情况下(它本身是一个链并且没有相关的 CA 证书),这只需要是 server 证书。
Java/JSSE 通过一个
SSLContext
实现这一点,其中包含一个 TrustManager
,更具体地说是一个 X509ExtendedTrustManager
,它是 initialized from truststore。您可以从任何一组受信任的证书(甚至不需要来自文件)的代码中显式创建SSLContext
,或者使用使用默认信任库文件的默认上下文,除非被覆盖,否则默认为上面的文件名通过系统属性。
收到服务器证书链后,它会传递给上下文的 TrustManager 进行验证;在(许多!)其他检查中,在正常链的每个级别或自签名证书的单个级别,JSSE TrustManager 寻找锚证书(编辑),它是is所需的证书(相同的主题和(Subject)PublicKey) 或者是该证书的签名者(Subject 等于 Issuer),如果找到这样的锚点,它将用于验证证书链。请注意,如果使用 Subject Alternative Name 代替,则普通(CA 颁发的)叶证书的 Subject 可以为空 - 请参阅 rfc5280 和 rfc2818 - 但自签名证书不能,因为它有 Subject = Issuer 并且 Issuer must not是空的。不同实体(例如不同的服务器)的证书通常应具有不同的密钥,尽管单个实体可以具有多个具有相同密钥或不同密钥的证书,并且可能对应于多个服务器名称和/或地址。
(补充)这个锚点查找不使用别名,在验证过程中也不使用任何其他东西,这就是为什么没有也不需要指定别名的原因,以及(某些)其他目的所需的别名在 KeyStore 文件或对象中对于此目的没有意义。
如果证书通常被确定为有效,对于 some TLS 应用程序(特别是 HTTPS),验证器 also 检查它是否适用于正确的服务器,特别是 Subject 字段中的 CommonName 属性,或 Subject Alternative 中的条目名称扩展(如果存在)(对于公共 CA,它始终是并且至少已经存在十年)与 URL 中的主机 DNS 名称或 IP 地址相匹配。在旧版本的 Java(通过 6 IIRC)中,这不是在 JSSE 中完成的,而是在调用应用程序或库中完成的,例如
HttpsURLConnection
,作为遗留物,它仍然可以选择使用自己的 HostnameVerifier
.
所有这些都可以通过使用自定义
TrustManager
代替标准的来改变,有些东西像 Apache HttpClient
这样做是有效的,但你会在这里找到(太多)答案和其他一些 Stacks 推荐你'通过使用只接受任何证书的绝育 TrustManager
解决' TLS 错误,无论它是否实际有效和正确,因此愉快地连接敏感数据并将敏感数据发送给任何设法拦截 IP 的攻击者,或接受来自任何攻击者的更改交通,现在通常很容易。
别名是一种直接访问证书的方法,但您的密钥库也有关于证书的其他信息。 X.509 证书有一个名为 SAN(Subject Alternative name)的字段,其中包含证书的 DNS 信息。当您尝试连接到特定 URL 时,会在密钥库中查找 SAN 中相应的 DNS 名称并获取正确的证书。
希望它能澄清您对 java 不要求别名的疑问。放心,这个过程没有任何随机性。