使用的是哪个证书?

8
我有一个来自供应商的样例命令行Java应用程序,它依赖于SSL身份验证。我拥有供应商的证书,可以在我的Java 7 cacerts文件中看到它们(Windows,c:\ program files \ java \ jdk1.7.0_07 \ jre \ lib \ security \ cacerts)。如果我打开Java 8 cacerts文件,它们就不在那里了(c:\ program files \ java \ jre1.8.0_66 \ lib \ security \ cacerts)。
如果我设置一个路径让Java 8处于首位,则该程序会正常运行。如果我改变路径让Java 7处于首位,则该程序会因证书错误而失败:
C:\project\tryCerts\Demo2>path=c:\program files\java\jdk1.7.0_07\bin;c:\program files\java\jre1.8.0_66\bin


C:\project\tryCerts\Demo2>java -jar vendorCmd.jar user1 password2 environment3
Dec 22, 2015 11:11:35 AM [com.sun.xml.ws.policy.jaxws.PolicyConfigParser]  parse
INFO: WSP5018: Loaded WSIT configuration from file: jar:file:/C:/project/tryCerts/Demo2/vendorCmd/dist/vendorCmd.jar!/META-INF/wsit-client.xml.
Unable to log in: com.sun.xml.ws.client.ClientTransportException: HTTP transport error: javax.net.ssl.SSLHandshakeException: sun.security.validator.Va
lidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to re
quested target

C:\project\tryCerts\Demo2>path=c:\program files\java\jre1.8.0_66\bin;c:\program files\java\jdk1.7.0_07\bin

C:\project\tryCerts\Demo2>java -jar vendorCmd.jar acc03\acc03_ws_user accwbS3rv!ceS acc03_p_production
Dec 22, 2015 11:21:34 AM [com.sun.xml.ws.policy.jaxws.PolicyConfigParser]  parse
INFO: WSP5018: Loaded WSIT configuration from file: jar:file:/C:/project/tryCerts/Demo2/vendorCmd/dist/vendorCmd.jar!/META-INF/wsit-client.xml.
logged in
Dec 22, 2015 11:21:35 AM [com.sun.xml.ws.policy.jaxws.PolicyConfigParser]  parse
INFO: WSP5018: Loaded WSIT configuration from file: jar:file:/C:/project/tryCerts/Demo2/vendorCmd/dist/vendorCmd.jar!/META-INF/wsit-client.xml.
Signed Info:org.jcp.xml.dsig.internal.dom.DOMSignedInfo@3f071328
AccountNumber: 279105/ Firstname: null/ LastName: null
AccountNumber: 1005118/ Firstname: null/ LastName: COMPANY1
AccountNumber: 2102765/ Firstname: null/ LastName: COMPANY2
AccountNumber: 2101373/ Firstname: null/ LastName: COMPANY3
AccountNumber: 2119664/ Firstname: null/ LastName: COMPANY4
AccountNumber: 2119668/ Firstname: null/ LastName: ET CETERA

C:\project\tryCerts\Demo2>dir/s cacerts
 Volume in drive C is OS
 Volume Serial Number is 9896-211D
File Not Found

C:\project\tryCerts\Demo2>

这恰恰与我预期的相反——在Java 7文件夹中,是cacerts文件具有供应商证书链,而Java 8则没有。然而,在Java 7上运行该程序会导致认证错误,而在Java 8上运行则成功。
有人能告诉我应该查找什么来解释这个问题吗?

2
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Anya Shenanigans
谢谢!这证实了我认为它们是什么的想法。但我仍然想知道为什么没有供应商证书的那个可以工作,而有供应商证书的那个却不能工作。 - arcy
我这里没有有用的方法 - 通常我会在Java之外验证供应商链,然后检查两个Java信任存储中链的每个元素; 除此之外,没有真正的想法。 - Anya Shenanigans
@Petesh 如果您能把您的建议放到答案中,我会接受它——它回答了最初的问题,并引导我找到了总体答案。我倾倒了两个命令的输出并进行了比较,发现其中一个提到了“可信证书”,而另一个没有。我还没有弄清楚细节,但看起来就是这样。我最初问的是如何找出正在使用哪个 cacert 存储库,而您已经回答了这个问题(我应该考虑到)。 - arcy
2个回答

12
为了确定正在使用的信任存储库,而不必使用像strace(Linux)和process explorer(Windows)这样的工具,您可以将调试标志-Djavax.net.debug=trustmanager传递给Java命令行,它会转储所有与SSL相关的调试信息(我在原始评论中提到了all,但这会使输出更加杂乱无章)。
java -Djavax.net.debug=trustmanager -jar vendorCmd.jar user1 password2 environment3

在调试输出的前几行中,将会有一行:
trustStore is: <path to>cacerts

这表示正在使用的信任存储。

通过添加 ssl 选项 (trustmanager,ssl),它还会转储所有被添加到 JVM 认为可信任证书列表中的受信任证书。这可以用于验证您认为在信任存储中的证书实际上是否在信任存储中 - 在这种情况下,您应该能够在列表中看到供应商的证书。

javax.net.debug 的 调试选项完整列表 在 JSSE 参考指南中有详细说明。您可以使用 =help 来获取相对较短的标志使用消息。

示例代码和测试运行:

import java.net.URL;
import java.io.BufferedInputStream;

public class pull_url {
    public static void main(String args[]) throws Exception {
        for (String arg : args) {
            downloadUsingUrl(arg);
        }
    }

    public static void downloadUsingUrl(String stringurl) throws Exception {
        URL url = new URL(stringurl);
        BufferedInputStream bis = new BufferedInputStream(url.openStream());
        bis.close();
    }
}

执行结果的输出:

$ java -Djavax.net.debug=trustmanager pull_url https://google.com/
javax.net.ssl|DEBUG|10|main|2023-05-06 13:40:20.584 IST|TrustStoreManager.java:162|Inaccessible trust store: /Users/anysh/Library/Java/JavaVirtualMachines/jdk-19.0.1.jdk/Contents/Home/lib/security/jssecacerts
javax.net.ssl|DEBUG|10|main|2023-05-06 13:40:20.595 IST|TrustStoreManager.java:113|trustStore is: /Users/anysh/Library/Java/JavaVirtualMachines/jdk-19.0.1.jdk/Contents/Home/lib/security/cacerts
trustStore type is: pkcs12
trustStore provider is:
the last modified time is: Wed Sep 14 17:16:16 IST 2022
javax.net.ssl|DEBUG|10|main|2023-05-06 13:40:20.595 IST|TrustStoreManager.java:334|Reload the trust store
javax.net.ssl|DEBUG|10|main|2023-05-06 13:40:20.620 IST|TrustStoreManager.java:342|Reload trust certs
javax.net.ssl|DEBUG|10|main|2023-05-06 13:40:20.620 IST|TrustStoreManager.java:347|Reloaded 89 trust certs

在这种情况下,第二行指示正在使用的cacerts文件。

我不得不使用-Djavax.net.debug=allssl不足以打印信任存储位置。 - Juraj Martinka
1
好的 - 仅针对 cacerts 文件的标志是 trustmanager;我会更新一个示例。 - Anya Shenanigans

3
非常感谢Anya Shenanigans的回复。 只是想说,对于我的情况,我不得不使用
-Djavax.net.debug=all

不是ssl选项(我不确定为什么)。 如果使用该选项,正如Anya所说,控制台将显示:

javax.net.ssl|DEBUG|01|main|2023-02-26 11:06:43.622 CET|TrustStoreManager.java:112|trustStore is: 

在运行Java命令时添加选项。如果使用IntelliJIdea,请转到您的应用程序的Run/Debug配置,点击修改选项(默认情况下它将被隐藏),并添加“VM选项”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接