直接在文件系统上使用 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 证书需要测试
证书在我的文件系统上
使用文件系统中的证书符合我的工作流程
我不想使用
openssl
或keytool
我不想执行密钥存储维护
如何在文件系统上获取格式良好的 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 请求?的主要内容,如果未能解决你的问题,请参考以下文章
Docker - 通过IDEA和CA证书加密远程链接到服务器上的Docker
如何为Amazon EMR生成trustedCertificates.pem和certificateChain.pem文件?