【发布时间】:2018-12-23 11:11:34
【问题描述】:
我有一个由两个文件(.crt 和 .key)组成的客户端证书,我希望将其导入到 java KeyStore 中,然后在 SSLContext 中使用 Apache 的 HTTPClient 发送 HTTP 请求。但是,我似乎找不到以编程方式执行此操作的方法,我发现的大多数其他问题要么指向外部工具,要么不适合我的情况。
我的证书使用典型的“BEGIN CERTIFICATE”编码,后跟一个 Base64 编码字符串,密钥使用“BEGIN RSA PRIVATE KEY”,然后是另一个 Base64 编码字符串。
这是我目前得到的:
private static SSLContext createSSLContext(File certFile, File keyFile) throws IOException {
try {
PEMParser pemParser = new PEMParser(new FileReader(keyFile));
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(new BouncyCastleProvider());
Object object = pemParser.readObject();
KeyPair kp = converter.getKeyPair((PEMKeyPair) object);
PrivateKey privateKey = kp.getPrivate();
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
FileInputStream stream = new FileInputStream(certFile);
X509Certificate cert = (X509Certificate) certFactory.generateCertificate(stream);
KeyStore store = KeyStore.getInstance("JKS");
store.load(null);
store.setCertificateEntry("certificate", cert);
store.setKeyEntry("private-key", privateKey, "changeit".toCharArray(), new Certificate[] { cert });
SSLContext sslContext = SSLContexts.custom()
.loadKeyMaterial(store, "changeit".toCharArray())
.build();
return sslContext;
} catch (IOException | NoSuchAlgorithmException | CertificateException | KeyStoreException | KeyManagementException | UnrecoverableKeyException e) {
throw new IOException(e);
}
}
堆栈跟踪:
java.io.IOException: java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: 无效的密钥格式 在 me.failedshack.ssltest.SSLTest.createSSLContext(SSLTest.java:80) 在 me.failedshack.ssltest.SSLTest.main(SSLTest.java:31)
原因:java.security.spec.InvalidKeySpecException:java.security.InvalidKeyException:无效的密钥格式 在 java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:216) 在 java.base/java.security.KeyFactory.generatePrivate(KeyFactory.java:390) 在 me.failedshack.ssltest.SSLTest.createSSLContext(SSLTest.java:62) ... 1 更多
原因:java.security.InvalidKeyException:无效的密钥格式 在 java.base/sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:330) 在 java.base/sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:355) 在 java.base/sun.security.rsa.RSAPrivateCrtKeyImpl.(RSAPrivateCrtKeyImpl.java:91) 在 java.base/sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(RSAPrivateCrtKeyImpl.java:75) 在 java.base/sun.security.rsa.RSAKeyFactory.generatePrivate(RSAKeyFactory.java:315) 在 java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:212) ... 3 更多
遗憾的是,在从文件生成私钥时,我不断收到 InvalidKeyException。
【问题讨论】:
-
请跟踪堆栈。注意你不应该打电话给
setCertificateEntry(),只能打电话给setKeyEntry()。 -
您还需要用
KeyManager来初始化SSLContext,而不是TrustManager。否则永远找不到你的私钥。 -
而且您也无法将私钥转换为公钥。这没什么意义。
-
@EJP 对不起,PublicKey 演员,这是我玩弄的东西,不小心复制到了问题中。您对 KeyManager 的看法是正确的。我已经修改了问题。
-
这个异常只能说明它所说的:密钥文件有问题。你能用 OpenSSL 阅读它吗?
标签: java ssl https apache-httpclient-4.x client-certificates