Java 是否支持 Let's Encrypt 证书? [英] Does Java support Let's Encrypt certificates?

查看:23
本文介绍了Java 是否支持 Let's Encrypt 证书?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个 Java 应用程序,它通过 HTTP 查询远程服务器上的 REST API.出于安全原因,此通信应切换为 HTTPS.

I am developing a Java application that queries a REST API on a remote server over HTTP. For security reasons this communication should be switched to HTTPS.

既然 Let's Encrypt 开始了他们的公开测试版,我想知道 Java 当前是否有效(或已确认)将来使用)默认使用他们的证书.

Now that Let's Encrypt started their public beta, I'd like to know if Java currently works (or is confirmed to be working in the future) with their certificates by default.

Let's Encrypt 的中间由 IdenTrust 交叉签名,这应该是个好消息.但是,我在此命令的输出中找不到这两个中的任何一个:

Let's Encrypt got their intermediate cross-signed by IdenTrust, which should be good news. However, I cannot find any of these two in the output of this command:

keytool -keystore "..libsecuritycacerts" -storepass changeit -list

我知道可以在每台机器上手动添加受信任的 CA,但由于我的应用程序应该可以免费下载和执行,无需任何进一步配置,我正在寻找开箱即用"的解决方案.你有什么好消息要告诉我吗?

I know that trusted CAs can be added manually on each machine, but since my application should be free to download and executable without any further configuration, I am looking for solutions that work "out of the box". Do you have good news for me?

推荐答案

[Update 2016-06-08:根据 https://bugs.openjdk.java.net/browse/JDK-8154757 IdenTrust CA 将包含在 Oracle Java 8u101 中.]

[Update 2016-06-08: According to https://bugs.openjdk.java.net/browse/JDK-8154757 the IdenTrust CA will be included in Oracle Java 8u101.]

[2016-08-05 更新:Java 8u101 已经发布并且确实包含 IdenTrust CA:发行说明]

[Update 2016-08-05: Java 8u101 has been released and does indeed include the IdenTrust CA: release notes]

Java 是否支持 Let's Encrypt 证书?

Does Java support Let's Encrypt certificates?

是的.Let's Encrypt 证书只是一个普通的公钥证书.Java 支持它(根据 Let's Encrypt Certificate Compatibility,对于 Java 7 >= 7u111 和 Java 8>= 8u101).

Yes. The Let's Encrypt certificate is just a regular public key certificate. Java supports it (according to Let's Encrypt Certificate Compatibility, for Java 7 >= 7u111 and Java 8 >= 8u101).

Java 是否信任 Let's Encrypt 开箱即用的证书?

Does Java trust Let's Encrypt certificates out of the box?

否/这取决于JVM.高达 8u66 的 Oracle JDK/JRE 信任库既不包含 Let's Encrypt CA,也不包含对其进行交叉签名的 IdenTrust CA.new URL("https://letsencrypt.org/").openConnection().connect(); 例如导致 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException.

No / it depends on the JVM. The truststore of Oracle JDK/JRE up to 8u66 contains neither the Let's Encrypt CA specifically nor the IdenTrust CA that cross signed it. new URL("https://letsencrypt.org/").openConnection().connect(); for example results in javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException.

但是,您可以提供自己的验证器/定义包含所需根 CA 的自定义密钥库或将证书导入 JVM 信任库.

You can however provide your own validator / define a custom keystore that contains the required root CA or import the certificate into the JVM truststore.

https://community.letsencrypt.org/t/will-the-cross-root-cover-trust-by-the-default-list-in-the-jdk-jre/134/10 也讨论了这个话题.

以下是一些示例代码,展示了如何在运行时将证书添加到默认信任库.您只需要添加证书(从 firefox 导出为 .der 并放入类路径中)

Here is some example code that shows how to add a certificate to the default truststore at runtime. You'll just need to add the certificate (exported from firefox as .der and put in classpath)

基于 如何获取 Java 中受信任的根证书列表?http://developer.android.com/training/articles/security-ssl.html#UnknownCa

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.TrustManagerFactory;

public class SSLExample {
    // BEGIN ------- ADDME
    static {
        try {
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            Path ksPath = Paths.get(System.getProperty("java.home"),
                    "lib", "security", "cacerts");
            keyStore.load(Files.newInputStream(ksPath),
                    "changeit".toCharArray());

            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            try (InputStream caInput = new BufferedInputStream(
                    // this files is shipped with the application
                    SSLExample.class.getResourceAsStream("DSTRootCAX3.der"))) {
                Certificate crt = cf.generateCertificate(caInput);
                System.out.println("Added Cert for " + ((X509Certificate) crt)
                        .getSubjectDN());

                keyStore.setCertificateEntry("DSTRootCAX3", crt);
            }

            if (false) { // enable to see
                System.out.println("Truststore now trusting: ");
                PKIXParameters params = new PKIXParameters(keyStore);
                params.getTrustAnchors().stream()
                        .map(TrustAnchor::getTrustedCert)
                        .map(X509Certificate::getSubjectDN)
                        .forEach(System.out::println);
                System.out.println();
            }

            TrustManagerFactory tmf = TrustManagerFactory
                    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
            tmf.init(keyStore);
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, tmf.getTrustManagers(), null);
            SSLContext.setDefault(sslContext);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    // END ---------- ADDME

    public static void main(String[] args) throws IOException {
        // signed by default trusted CAs.
        testUrl(new URL("https://google.com"));
        testUrl(new URL("https://www.thawte.com"));

        // signed by letsencrypt
        testUrl(new URL("https://helloworld.letsencrypt.org"));
        // signed by LE's cross-sign CA
        testUrl(new URL("https://letsencrypt.org"));
        // expired
        testUrl(new URL("https://tv.eurosport.com/"));
        // self-signed
        testUrl(new URL("https://www.pcwebshop.co.uk/"));

    }

    static void testUrl(URL url) throws IOException {
        URLConnection connection = url.openConnection();
        try {
            connection.connect();
            System.out.println("Headers of " + url + " => "
                    + connection.getHeaderFields());
        } catch (SSLHandshakeException e) {
            System.out.println("Untrusted: " + url);
        }
    }

}

这篇关于Java 是否支持 Let's Encrypt 证书?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆