收到致命警报:bad_certificate

Posted

技术标签:

【中文标题】收到致命警报:bad_certificate【英文标题】:Received fatal alert: bad_certificate 【发布时间】:2012-08-01 17:44:06 【问题描述】:

我正在尝试设置 SSL Socket 连接(并且正在客户端上执行以下操作)

    我生成证书签名请求以获取已签名的客户端证书

    现在我有一个私钥(在 CSR 期间使用)、一个签名的客户端证书和根证书(带外获得)。

    我将私钥和签名的客户端证书添加到证书链中,并将其添加到密钥管理器中。以及信任管理器的根证书。 但我收到一个错误的证书错误。

我很确定我使用的是正确的证书。我也应该将签名的客户端证书添加到信任管理器吗?试过了,还是不行。

//I add the private key and the client cert to KeyStore ks
FileInputStream certificateStream = new FileInputStream(clientCertFile);
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
java.security.cert.Certificate[] chain = ;
chain = certificateFactory.generateCertificates(certificateStream).toArray(chain);
certificateStream.close();
String privateKeyEntryPassword = "123";
ks.setEntry("abc", new KeyStore.PrivateKeyEntry(privateKey, chain),
        new KeyStore.PasswordProtection(privateKeyEntryPassword.toCharArray()));

//Add the root certificate to keystore jks
FileInputStream is = new FileInputStream(new File(filename));
CertificateFactory cf = CertificateFactory.getInstance("X.509");
java.security.cert.X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
System.out.println("Certificate Information: ");
System.out.println(cert.getSubjectDN().toString());
jks.setCertificateEntry(cert.getSubjectDN().toString(), cert);

//Initialize the keymanager and trustmanager and add them to the SSL context
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, "123".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(jks);

我需要在这里创建某种证书链吗? 我也有一个带有这些组件的 p12,并且在使用非常相似的代码后,将私钥添加到 keymanager 并将根证书从 p12 添加到信任管理器,我可以使它工作。但现在我需要让它在没有 p12 的情况下工作。

编辑:请求堆栈跟踪。希望这应该足够了。 (注意:我掩盖了文件名)

Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1720)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:954)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1165)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1149)
at client.abc2.openSocketConnection(abc2.java:33)
at client.abc1.runClient(abc1.java:63)
at screens.app.abc.validateLogin(abc.java:197)
... 32 more

【问题讨论】:

【参考方案1】:

您还需要将根证书添加到密钥库。

【讨论】:

再次感谢。我将客户端证书和私钥添加到第一个密钥库 (k1),然后将 k1 添加到 keymanagerfactory。然后根证书到 keystore (k2) 和 k2 到 trustmanagerfactory【参考方案2】:

删除这两行时出现此错误。如果您知道您的密钥库具有正确的证书,请确保您的代码正在查看正确的密钥库。

System.setProperty("javax.net.ssl.keyStore", <keystorePath>));
System.setProperty("javax.net.ssl.keyStorePassword",<keystorePassword>));

我还需要这个 VM 参数: -Djavax.net.ssl.trustStore=/app/certs/keystore.jk 有关更多详细信息,请参见此处: https://***.com/a/34311797/1308453

【讨论】:

你当然做到了。没有默认密钥库。不是这个问题的答案。 我同意这不是问题的答案,但它是相关的,并且可以帮助那些通过一般“bad_certificate”搜索偶然发现这篇文章的人。这正是我的情况。【参考方案3】:

只要服务器证书签名有效,你只需要照常打开连接即可:

import java.net.*;
import java.io.*;

public class URLConnectionReader 
    public static void main(String[] args) throws Exception 
        URL google = new URL("https://www.google.com/");
        URLConnection yc = google.openConnection();
        BufferedReader in = new BufferedReader(new InputStreamReader(
                                    yc.getInputStream()));
        String inputLine;
        while ((inputLine = in.readLine()) != null) 
            System.out.println(inputLine);
        in.close();
    

请注意,该 URL 具有 HTTPS 架构以指示使用 SSL。

如果服务器的证书已签名,但您使用的 IP 地址/域名与证书中的不同,则可以绕过主机名验证:

HostnameVerifier hv = new HostnameVerifier() 
    public boolean verify(String urlHostName,SSLSession session) 
        return true;
    
;

HttpsURLConnection.setDefaultHostnameVerifier(hv);

如果证书未签名,则需要将其添加到 JVM 使用的密钥库 (useful commands)。

【讨论】:

正在“像往常一样打开连接”并且它没有工作。他没有使用HTTPS。您不需要用于 SSL 的 HostnameVerifier,仅用于 HTTPS。您发布的内容根本不安全,应该注意,或者根本不发布。没有答案。

以上是关于收到致命警报:bad_certificate的主要内容,如果未能解决你的问题,请参考以下文章

Java - 收到致命警报:handshake_failure

收到致命警报:bad_certificate

SSL:收到致命警报:handshake_failure

收到致命警报:handshake_failure,已添加信任库

信任 Websocket SSL - 收到致命警报:handshake_failure

OWASP ZAP - SSLHandshakeException:收到致命警报:handshake_failure