仍然收到 Received fatal alert: bad_certificate ,
still getting Received fatal alert: bad_certificate ,
我将密钥和证书(组合)放入一个 cert.pem 文件中,
我得到,
"exception": "javax.net.ssl.SSLHandshakeException",
"message": "Received fatal alert: bad_certificate",
pem file is right, but i think problem is how i generating jks keystore file.
.pem 证书格式
BEGIN CERTIFICATE
...
END CERTIFICATE
BEGIN CERTIFICATE
...
END CERTIFICATE
BEGIN RSA PRIVATE KEY
...
END RSA PRIVATE KEY###`
将它与 keytool 命令结合使用命令是
keytool -import -trustcacerts -alias yourdomain -file combined.pem -keystore yourkeystore.jks
java代码为
public class HttpsTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
// TODO Auto-generated method stub
}
@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
// TODO Auto-generated method stub
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
请求是
FileInputStream instream = new FileInputStream(
new File(this.resourcePath()+"/path_to.jks")
);
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(instream, "password".toCharArray());
SSLContext sslContext = SSLContexts.custom()
.loadKeyMaterial(keyStore, "password".toCharArray()) // use null as second param if you don't have a separate key password
.build();
sslContext.init(null,new X509TrustManager[]{new HttpsTrustManager()}, new SecureRandom());
HttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build();
HttpResponse response = httpClient.execute(
new HttpPost("https://url")
);
HttpEntity entity = response.getEntity();
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
EntityUtils.consume(entity);
当您使用 Apache SSLContexts.custom().loadKeyMaterial().build()
时,它会使用指定的密钥库和默认的信任管理器初始化构建的上下文。然后你调用 sslContext.init()
到 re——用 no keymanager 和指定的 trustmanager 初始化它;这将忽略并丢弃先前的初始化。因此,您的上下文没有密钥管理器,无法进行客户端身份验证。
你需要保持一致。要么使用 Apache 并给(相同的)构建器 both loadKeyMaterial
and loadTrustMaterial
对应于你想要的 - 在特别是 httpclient 4.5.4 添加了 org.apache.http.conn.ssl.TrustAllStrategy
实现了 "cheerfully let all thieves and crooks see and change my supposedly secure data"。或者,使用 JSSE 使用零安全信任管理器和从密钥库创建的密钥管理器(以及显式 SecureRandom
如果你喜欢但如果你省略它默认)。
但是,这可能不起作用,因为仅当 yourdomain
是与您导入的证书链匹配的预先存在的 PrivateKeyEntry 时,您显示的 keytool
命令才是正确的。使用 keytool -list -alias yourdomain
确保它是 PrivateKeyEntry 而不是 TrustedCertEntry。如果没有,并且如果您需要使用 PEM 文件中的私钥(而不是已经存在于密钥库中的私钥),您需要首先使用 OpenSSL 将密钥 and 证书链转换为 PKCS12,并且然后根据您的 Java 可能 使用 keytool
将 PKCS12 转换为 JKS。为此,在几个堆栈上有几十个 Q(和 A)。
我将密钥和证书(组合)放入一个 cert.pem 文件中,
我得到,
"exception": "javax.net.ssl.SSLHandshakeException",
"message": "Received fatal alert: bad_certificate",
pem file is right, but i think problem is how i generating jks keystore file.
.pem 证书格式
BEGIN CERTIFICATE
...
END CERTIFICATE
BEGIN CERTIFICATE
...
END CERTIFICATE
BEGIN RSA PRIVATE KEY
...
END RSA PRIVATE KEY###`
将它与 keytool 命令结合使用命令是
keytool -import -trustcacerts -alias yourdomain -file combined.pem -keystore yourkeystore.jks
java代码为
public class HttpsTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
// TODO Auto-generated method stub
}
@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
// TODO Auto-generated method stub
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
请求是
FileInputStream instream = new FileInputStream(
new File(this.resourcePath()+"/path_to.jks")
);
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(instream, "password".toCharArray());
SSLContext sslContext = SSLContexts.custom()
.loadKeyMaterial(keyStore, "password".toCharArray()) // use null as second param if you don't have a separate key password
.build();
sslContext.init(null,new X509TrustManager[]{new HttpsTrustManager()}, new SecureRandom());
HttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build();
HttpResponse response = httpClient.execute(
new HttpPost("https://url")
);
HttpEntity entity = response.getEntity();
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
EntityUtils.consume(entity);
当您使用 Apache SSLContexts.custom().loadKeyMaterial().build()
时,它会使用指定的密钥库和默认的信任管理器初始化构建的上下文。然后你调用 sslContext.init()
到 re——用 no keymanager 和指定的 trustmanager 初始化它;这将忽略并丢弃先前的初始化。因此,您的上下文没有密钥管理器,无法进行客户端身份验证。
你需要保持一致。要么使用 Apache 并给(相同的)构建器 both loadKeyMaterial
and loadTrustMaterial
对应于你想要的 - 在特别是 httpclient 4.5.4 添加了 org.apache.http.conn.ssl.TrustAllStrategy
实现了 "cheerfully let all thieves and crooks see and change my supposedly secure data"。或者,使用 JSSE 使用零安全信任管理器和从密钥库创建的密钥管理器(以及显式 SecureRandom
如果你喜欢但如果你省略它默认)。
但是,这可能不起作用,因为仅当 yourdomain
是与您导入的证书链匹配的预先存在的 PrivateKeyEntry 时,您显示的 keytool
命令才是正确的。使用 keytool -list -alias yourdomain
确保它是 PrivateKeyEntry 而不是 TrustedCertEntry。如果没有,并且如果您需要使用 PEM 文件中的私钥(而不是已经存在于密钥库中的私钥),您需要首先使用 OpenSSL 将密钥 and 证书链转换为 PKCS12,并且然后根据您的 Java 可能 使用 keytool
将 PKCS12 转换为 JKS。为此,在几个堆栈上有几十个 Q(和 A)。