使用KeyStore与.crt

使用KeyStore与.crt

问题描述:

我需要集成一个应用程序与强制使用https的外部Web服务。此Web服务的作者为我提供了.crt文件,我应该使用它来提供https请求。经过一番调查,我发现下面的代码,它使用KeyStore类为安全HTTPS访问:使用KeyStore与.crt

 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(); 

在这段代码密钥库,需要输入流与密码trustStore.load(instream, password.toCharArray())一起。不过,据我所知,使用.crt文件时我们不需要密码。所以这种加载证书的方式并不适合我。同时,从我迄今为止发现的情况来看,我在这里提供的代码是配置HttpClient使用SSL证书的唯一方法。是否有任何解决方法来配置HttpClient使用.crt证书?

感谢,

安德烈

我假定Web服务为您提供一个自签名证书(即不是由知名CA签名)。如果它已经由Java的cacerts文件中的知名CA签名,则不需要执行任何操作。

否则,你有两个选择:

  1. 证书导入全球的cacerts密钥存储
  2. 启动与专用密钥库

在这两种情况下,你首先需要您的应用程序将crt文件转换为Java使用的jks keystore。你可以这样做:

$ keytool -import -keystore mykeystore.jks -storepass horsestaple 

注意,密钥工具需要创建JKS存储要提供的密码(以上horsestaple)。你可以放任何东西;如你所说,公共网站证书不需要密码保护,毕竟他们是公开的。

如果您正在做选项1,请备份您的cacerts并提供cacerts文件而不是mykeystore.jks。请参阅以下链接,了解cacerts的位置。对于这个选项,你已经全部设置了,你的应用程序应该通过HTTPS连接到Web服务,而不需要任何额外的配置,因为默认情况下Java会加载cacerts。

如果你正在做的选项2,这可能是至少首选测试阶段,你需要使用这个参数运行应用程序:

-Djavax.net.ssl.trustStore=mykeystore.jks 

这是一个JVM的参数,所以适当地提供它。这取决于你如何运行你的应用程序。

请注意,在这种情况下您将只有导入的证书,因此您的其他HTTPS连接将不起作用。您可以通过首先将标准cacerts复制到临时位置,将密钥导入并在上面的命令中使用它来避免这种情况。这将给你所有的标准证书,加上你需要的。

选项2的一个小缺点是,如果新证书被添加或撤销,您的特定于应用程序的密钥库不会被更新。如果这是一个问题,你可以在飞行合并密钥库,例如:

在这两种情况下,你现在应该能够只是做一个标准的网址提取,如例如在这里给出:

即:

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

  • cacerts的位置

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?

希望这有助于。

+0

第三种选择是直接将信任库用于客户端API,这是OP看起来像他们正在做的事情。这比你最初提出的两个选项中的任何一个都好,因为它不会干扰任何其他信任商店的使用。 –

+0

@ChristopherSchultz同意,如果OP想要使用原来的解决方案,当然可以。我想这取决于用例,如果分布在多个应用程序中,更新全局cacerts可能会更容易。 –

除非他们与应该用于验证连接他们他们 .crt文件,这表明他们正在使用自签名证书提供你,他们没有任何有用您提供。如果需要证书作为客户端,您需要的第一件事是公钥/私钥对,您可以从中生成一个您签署的CSR。没有其他人可以安全地提供除签名证书之外的任何内容。

如果他们已经提供了自己的(自签名?)证书,则需要将其加载到一个信任,而不是一个密钥库,通过keytool-trustcacerts选项,然后告诉Java使用信任,可以通过javax.net.ssl.trustStore系统属性或通过构建您自己的TrustManager并将其提供给自定义SSLContext,如JSSE参考指南中所述。