将 KeyStore 与 .crt 结合使用
using KeyStore with .crt
我需要将应用程序与强制使用 https 的外部 Web 服务集成。此 Web 服务的作者为我提供了 .crt 文件,我应该使用它来发出 https 请求。经过一番调查后,我发现以下代码使用 KeyStore class 进行安全的 https 访问:
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream instream = new FileInputStream(new File(file));
try {
trustStore.load(instream, password.toCharArray());
} finally {
instream.close();
}
SSLContext sslcontext =
SSLContexts.custom().loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()).build();
SSLConnectionSocketFactory sslsf =
new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1.2"}, null,
BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
HttpClients.custom().setSSLSocketFactory(sslsf).build();
在此代码中,KeyStore 需要输入流以及 密码 trustStore.load(instream, password.toCharArray())
;。但是,据我了解,我们在使用 .crt 文件时不需要密码。所以这种加载证书的方式不适合我。同时,根据我目前的发现,我在此处提供的代码是配置 HttpClient 以使用 SSL 证书的唯一方法。是否有任何解决方法来配置 HttpClient 以使用 .crt 证书?
谢谢,
安德烈
我假设 Web 服务正在为您提供自签名证书(即不是由知名 CA 签名的)。如果它已经由 Java 的 cacerts 文件中的知名 CA 签名,则您无需执行任何操作。
否则,您有几个选择:
- 将证书导入全局 cacerts 密钥库
- 使用特定于应用程序的密钥库启动您的应用程序
无论哪种情况,您首先需要将 crt 文件转换为 Java 使用的 jks 密钥库。您可以通过以下方式做到这一点:
$ keytool -import -keystore mykeystore.jks -storepass horsestaple
请注意,keytool 需要提供密码(horsestaple
以上)才能创建 jks 存储。你可以把任何东西放在那里;正如您所说,public 网站证书不需要密码保护,毕竟它们是 public。
如果您执行选项 1,请备份您的 cacerts 并提供 cacerts 文件而不是 mykeystore.jks。有关 cacerts 的位置,请参阅下面的 link。对于此选项,您已准备就绪,您的应用程序应通过 HTTPS 连接到 Web 服务,无需任何其他配置,因为 Java 默认加载 cacerts。
如果您正在执行选项 2,这可能至少在测试阶段是首选,您需要 运行 您的应用程序使用此参数:
-Djavax.net.ssl.trustStore=mykeystore.jks
这是一个 JVM 参数,因此请适当地提供它。这取决于您 运行 应用的方式。
请注意,在这种情况下您将只有导入的证书,因此您的其他 HTTPS 连接将不起作用。您可以通过首先将标准 cacerts 复制到一个临时位置,将密钥导入其中并在上面的命令中使用它来避免这种情况。这将为您提供所有标准证书,以及您需要的证书。
选项 2 的一个小缺点是,如果添加或撤销新证书,您的应用程序特定密钥库将不会更新。如果这是一个问题,您可以即时合并密钥库,例如:
- Registering multiple keystores in JVM
无论哪种情况,您现在都应该能够进行标准的 URL 提取,例如此处给出的示例:
即:
final URL url = new URL("https://example.com");
try(final InputStream in = url.openStream()){
//…
}
更多信息在这里:
- Keytool 和一般证书信息
https://docs.oracle.com/cd/E19830-01/819-4712/ablqw/index.html
- 证书位置
http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/keytool.html
- 导入自签名证书的更多选项
How to properly import a selfsigned certificate into Java keystore that is available to all Java applications by default?
希望这对您有所帮助。
除非他们向您提供他们的 .crt 文件,该文件应该用于验证 到[=25] 的连接=] 他们,这表明他们使用的是自签名证书,他们没有为您提供任何有用的信息。如果你需要一个证书作为客户端,你首先需要的是一个public/private密钥对,你可以从中生成一个CSR , 你得到签名。除了签名证书,没有其他人可以安全地提供任何这些。
如果他们提供了自己的(自签名?)证书,您需要通过 keytool
将其加载到 truststore,而不是密钥库使用 -trustcacerts
选项,然后通过 javax.net.ssl.trustStore
系统 属性 或构建您自己的 TrustManager
并将其提供给自定义 SSLContext
,如 JSSE 参考指南中所述。
我需要将应用程序与强制使用 https 的外部 Web 服务集成。此 Web 服务的作者为我提供了 .crt 文件,我应该使用它来发出 https 请求。经过一番调查后,我发现以下代码使用 KeyStore class 进行安全的 https 访问:
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream instream = new FileInputStream(new File(file));
try {
trustStore.load(instream, password.toCharArray());
} finally {
instream.close();
}
SSLContext sslcontext =
SSLContexts.custom().loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()).build();
SSLConnectionSocketFactory sslsf =
new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1.2"}, null,
BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
HttpClients.custom().setSSLSocketFactory(sslsf).build();
在此代码中,KeyStore 需要输入流以及 密码 trustStore.load(instream, password.toCharArray())
;。但是,据我了解,我们在使用 .crt 文件时不需要密码。所以这种加载证书的方式不适合我。同时,根据我目前的发现,我在此处提供的代码是配置 HttpClient 以使用 SSL 证书的唯一方法。是否有任何解决方法来配置 HttpClient 以使用 .crt 证书?
谢谢,
安德烈
我假设 Web 服务正在为您提供自签名证书(即不是由知名 CA 签名的)。如果它已经由 Java 的 cacerts 文件中的知名 CA 签名,则您无需执行任何操作。
否则,您有几个选择:
- 将证书导入全局 cacerts 密钥库
- 使用特定于应用程序的密钥库启动您的应用程序
无论哪种情况,您首先需要将 crt 文件转换为 Java 使用的 jks 密钥库。您可以通过以下方式做到这一点:
$ keytool -import -keystore mykeystore.jks -storepass horsestaple
请注意,keytool 需要提供密码(horsestaple
以上)才能创建 jks 存储。你可以把任何东西放在那里;正如您所说,public 网站证书不需要密码保护,毕竟它们是 public。
如果您执行选项 1,请备份您的 cacerts 并提供 cacerts 文件而不是 mykeystore.jks。有关 cacerts 的位置,请参阅下面的 link。对于此选项,您已准备就绪,您的应用程序应通过 HTTPS 连接到 Web 服务,无需任何其他配置,因为 Java 默认加载 cacerts。
如果您正在执行选项 2,这可能至少在测试阶段是首选,您需要 运行 您的应用程序使用此参数:
-Djavax.net.ssl.trustStore=mykeystore.jks
这是一个 JVM 参数,因此请适当地提供它。这取决于您 运行 应用的方式。
请注意,在这种情况下您将只有导入的证书,因此您的其他 HTTPS 连接将不起作用。您可以通过首先将标准 cacerts 复制到一个临时位置,将密钥导入其中并在上面的命令中使用它来避免这种情况。这将为您提供所有标准证书,以及您需要的证书。
选项 2 的一个小缺点是,如果添加或撤销新证书,您的应用程序特定密钥库将不会更新。如果这是一个问题,您可以即时合并密钥库,例如:
- Registering multiple keystores in JVM
无论哪种情况,您现在都应该能够进行标准的 URL 提取,例如此处给出的示例:
即:
final URL url = new URL("https://example.com");
try(final InputStream in = url.openStream()){
//…
}
更多信息在这里:
- Keytool 和一般证书信息
https://docs.oracle.com/cd/E19830-01/819-4712/ablqw/index.html
- 证书位置
http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/keytool.html
- 导入自签名证书的更多选项
How to properly import a selfsigned certificate into Java keystore that is available to all Java applications by default?
希望这对您有所帮助。
除非他们向您提供他们的 .crt 文件,该文件应该用于验证 到[=25] 的连接=] 他们,这表明他们使用的是自签名证书,他们没有为您提供任何有用的信息。如果你需要一个证书作为客户端,你首先需要的是一个public/private密钥对,你可以从中生成一个CSR , 你得到签名。除了签名证书,没有其他人可以安全地提供任何这些。
如果他们提供了自己的(自签名?)证书,您需要通过 keytool
将其加载到 truststore,而不是密钥库使用 -trustcacerts
选项,然后通过 javax.net.ssl.trustStore
系统 属性 或构建您自己的 TrustManager
并将其提供给自定义 SSLContext
,如 JSSE 参考指南中所述。