直接在文件系统上使用 PEM 编码的 CA 证书进行 HTTPS 请求?

Posted

技术标签:

【中文标题】直接在文件系统上使用 PEM 编码的 CA 证书进行 HTTPS 请求?【英文标题】:Use PEM Encoded CA Cert on filesystem directly for HTTPS request? 【发布时间】:2014-04-24 23:56:33 【问题描述】:

这类似于Import PEM into Java Key Store。但问题的答案使用 OpenSSL 进行转换,并使用工具将它们导入文件系统上的密钥存储中。

我正在尝试使用格式正确的 X509 证书作为信任锚:

static String CA_FILE = "ca-rsa-cert.pem";

public static void main(String[] args) throws Exception

    KeyStore ks = KeyStore.getInstance("JKS");
    ks.load(new FileInputStream(CA_FILE), null);

    TrustManagerFactory tmf = TrustManagerFactory
                .getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(ks);

    SSLContext context = SSLContext.getInstance("TLS");
    context.init(null, tmf.getTrustManagers(), null);

    // Redirected through hosts file
    URL url = new URL("https://example.com:8443");

    HttpsURLConnection connection = (HttpsURLConnection) url
            .openConnection();
    connection.setSSLSocketFactory(context.getSocketFactory());

    ...

当我尝试运行程序时,出现错误:

$ java TestCert 
Exception in thread "main" java.io.IOException: Invalid keystore format
    at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:650)
    at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:55)
    at java.security.KeyStore.load(KeyStore.java:1214)
    at TestCert.main(TestCert.java:30)

我也尝试了KeyStore ks = KeyStore.getInstance("PEM");getInstance("X509");,但它们也不起作用。

我知道 Java 支持 PEM 和 DER 编码证书,因为这是 Web 服务器发送给客户端的内容。但是KeyStoreType 似乎都不符合我的需求,所以我怀疑我没有为此使用正确的 API。

我想直接使用它们而将它们导入长寿KeyStore的原因是:

    有数百个 PEM 证书需要测试 证书在我的文件系统上 使用文件系统中的证书符合我的工作流程 我不想使用opensslkeytool 我不想执行密钥存储维护

如何在文件系统上获取格式良好的 PEM 编码证书并直接使用它?

【问题讨论】:

“我知道 Java 支持 PEM 编码证书,因为这是 Web 服务器发送给客户端的内容”是什么意思? 谢谢迈克。好吧,我不知道如何回答。困惑在哪里? 在客户端/Web 服务器安全事务(如 TLS 1.1/1.2)中通过网络发送的证书通常在不使用 PEM 的情况下以 DER 编码发送。这是因为 PEM (Base64) 每 3 个字节的二进制数据使用 4 个字节,将 DER 编码的二进制值的大小至少增加了 25%。 另外值得一提的是,CertificateFactory 允许您从纯 DER 或 PEM 格式生成证书。您可以使用CertificateFactory 创建一个Certificate 对象,将其类型转换为X509Certificate 并尝试将其加载到您的KeyStore 好点迈克。我忘记了这一切。 (我也没有 DER 编码的证书)。 【参考方案1】:

我在Set certificate for KeyStore.TrustedCertificateEntry? 尝试以另一种方式执行此操作时找到了答案。它基于 Vit Hnilica 在loading a certificate from keystore 的回答。我将把这个问题留给这个答案,因为大多数 Stack Overflow 的答案都以“使用openssl 转换,然后使用keytool ...”开头。

String CA_FILE = ...;

FileInputStream fis = new FileInputStream(CA_FILE);
X509Certificate ca = (X509Certificate) CertificateFactory.getInstance(
        "X.509").generateCertificate(new BufferedInputStream(fis));

KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, null);
ks.setCertificateEntry(Integer.toString(1), ca);

TrustManagerFactory tmf = TrustManagerFactory
        .getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
...

【讨论】:

以上是关于直接在文件系统上使用 PEM 编码的 CA 证书进行 HTTPS 请求?的主要内容,如果未能解决你的问题,请参考以下文章

通过Go语言创建CA与签发证书

Docker - 通过IDEA和CA证书加密远程链接到服务器上的Docker

如何为Amazon EMR生成trustedCertificates.pem和certificateChain.pem文件?

mitmproxy-ca-cert.pem手机证书文件安装(一直安装不上,折磨我了两天!)

k8s部署使用CFSSL创建证书

ssl证书 只有crt文件 但是使用时需要key或pem文件 请问如何转换