【问题标题】:still getting Received fatal alert: bad_certificate ,仍然收到致命警报:bad_certificate,
【发布时间】:2018-05-22 05:31:50
【问题描述】:

我将密钥和证书(组合)到一个 cert.pem 文件中, 我得到了, “异常”:“javax.net.ssl.SSLHandshakeException”, "message": "收到致命警报:bad_certificate", pem file is right, but i think problem is how i generating jks keystore file.

.pem 证书格式

开始证书

...

结束证书

开始证书

...

结束证书

开始 RSA 私钥

...

结束 RSA 私钥###`

将它与 keytool comand comand is 结合起来

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);

【问题讨论】:

    标签: java spring ssl pem jks


    【解决方案1】:

    当您使用 Apache SSLContexts.custom().loadKeyMaterial().build() 时,它会使用指定的密钥库和默认的信任管理器初始化构建的上下文。然后调用sslContext.init()重新-使用no keymanager 和指定的trustmanager 对其进行初始化;这将忽略并丢弃先前的初始化。因此,您的上下文没有密钥管理器,并且无法进行客户端身份验证。

    你需要保持一致。要么使用 Apache 并给(相同的)构建器 both loadKeyMaterial loadTrustMaterial 对应于您想要的 - 特别是 httpclient 4.5.4 添加 org.apache.http.conn.ssl.TrustAllStrategy实现“让所有小偷和骗子看到并更改我所谓的安全数据”。或者,使用 JSSE 直接创建一个 SSLContext.getInstance().init() 它(一次!)使用您的零安全信任管理器和从您的密钥库创建的密钥管理器(如果您愿意,还可以使用显式 SecureRandom省略它的默认值)。

    但是,这可能不起作用,因为只有当 yourdomain 是与您导入的证书链匹配的预先存在的 PrivateKeyEntry 时,您显示的 keytool 命令才是正确的。使用keytool -list -alias yourdomain 确保它是 PrivateKeyEntry 而不是 TrustedCertEntry。如果没有,并且如果您需要使用 PEM 文件中的私钥(而不是已经在密钥库中的私钥),您需要首先使用 OpenSSL 将密钥 证书链转换为 PKCS12,然后根据您的 Java 也许使用 keytool 将 PKCS12 转换为 JKS。为此,在几个堆栈上有几十个 Q(和 As)。

    【讨论】:

    • 我将转换为 pkcs12,一切正常,我使用 InstallCert.java 安装我的证书,谢谢,我也更改了 HttpClients.custom().setSSLContext(sslContext)。到 HttpClients.custom().setSSLFactory(factory)