使用KeyStore和.crt

时间:2016-08-09 12:55:23

标签: java ssl https secure-crt

我需要将应用程序与外部Web服务集成,强制使用https。这个Web服务的作者为我提供了.crt文件,我应该用它来发出https请求。经过一些调查后,我发现以下代码使用KeyStore类进行安全的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证书?

谢谢,

安德烈

2 个答案:

答案 0 :(得分:1)

我认为Web服务正在为您提供自签名证书(即未由知名CA签名)。如果它已经由Java的cacerts文件中的知名CA签名,那么您不需要做任何事情。

否则,你有几个选择:

  1. 将证书导入global cacerts keystore
  2. 使用特定于应用程序的密钥库启动应用程序
  3. 在任何一种情况下,首先需要将crt文件转换为Java使用的jks密钥库。您可以通过以下方式执行此操作:

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

    请注意,keytool需要提供密码(上面为horsestaple)才能创建jks商店。你可以放任何东西;如你所知,公共网站证书不需要密码保护,毕竟它们是公开的。

    如果您正在执行选项1,请备份您的cacerts并提供cacerts文件而不是mykeystore.jks。请参阅以下链接,了解cacerts的位置。对于此选项,您已完成设置,您的应用程序应通过HTTPS连接到Web服务而无需任何其他配置,因为Java默认情况下会加载cacerts。

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

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

    这是一个JVM参数,因此请适当提供。这取决于您运行应用程序的方式。

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

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

    在任何一种情况下,您现在都应该只能进行标准的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

    • Cacerts location

    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?

    希望这有帮助。

答案 1 :(得分:0)

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

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