Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 证书链中的SSLHandshakeException行为_Java_Ssl - Fatal编程技术网

Java 证书链中的SSLHandshakeException行为

Java 证书链中的SSLHandshakeException行为,java,ssl,Java,Ssl,我已经使用此证书链的存储证书实现了证书固定: 证书1:云平台 证书2:Verizon(中级CA) 证书3:巴尔的摩(根CA) 但我注意到一种奇怪的行为: 行为1(预期):如果我只锁定证书1,我将获得 SSLHandshakeException错误,因为我需要包含所有 链中的证书 行为2(意外?):如果我只锁定了证书2,那么 中间CA,我根本不会得到任何SSLHandshakeException错误 你知道行为2是否是预期的吗?如果是,为什么?我的印象是,应该使用链中的所有证书,否则我将得

我已经使用此证书链的存储证书实现了证书固定:

  • 证书1:云平台
  • 证书2:Verizon(中级CA)
  • 证书3:巴尔的摩(根CA)
但我注意到一种奇怪的行为:

  • 行为1(预期):如果我只锁定证书1,我将获得 SSLHandshakeException错误,因为我需要包含所有 链中的证书
  • 行为2(意外?):如果我只锁定了证书2,那么 中间CA,我根本不会得到任何SSLHandshakeException错误
你知道行为2是否是预期的吗?如果是,为什么?我的印象是,应该使用链中的所有证书,否则我将得到一个SSLHandshakeException。谢谢

用代码更新

class SSLPinning {

void exec() {

    // Open InputStreams for each certificate
    InputStream baltimoreInputStream = getClass().getResourceAsStream("baltimore.cer");
    InputStream hcpmsInputStream = getClass().getResourceAsStream("hcpms_cert.cer");
    InputStream verizonInputStream = getClass().getResourceAsStream("verizon.cer");

    try {

        // CertificateFactory has the method that generates certificates from InputStream
        // Default type for getInstance is X.509
        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        // Create Certificate objects for each certificate
        Certificate baltimoreCertificate = cf.generateCertificate(baltimoreInputStream);
        Certificate hcpmsCertificate = cf.generateCertificate(hcpmsInputStream);
        Certificate verizonCertificate = cf.generateCertificate(verizonInputStream);

        // Create KeyStore and load it with our certificates
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(null, null);
        //keyStore.setCertificateEntry("hcpms", hcpmsCertificate);
        keyStore.setCertificateEntry("intermediate", verizonCertificate); //surprisingly, it works with just using the intermediate CA
        //keyStore.setCertificateEntry("root", baltimoreCertificate);

        // Create a TrustManagerFactory using KeyStore -- this is responsible in authenticating the servers
        // against our stored certificates
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(keyStore);

        // Create an SSLContext using TrustManagerFactory -- this will generate the SSLSocketFactory we will use
        // during HTTPS connection
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, tmf.getTrustManagers(), null);

        URL url = new URL("https://account.hanatrial.ondemand.com/");
        HttpsURLConnection httpsURLConnection = (HttpsURLConnection)url.openConnection();
        httpsURLConnection.setSSLSocketFactory(sslContext.getSocketFactory());
        httpsURLConnection.connect();
        System.out.print("Server authentication successful");

    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (SSLHandshakeException e) {
        System.out.println("Server authentication failed");
    } catch (IOException e) {
        e.printStackTrace();
    } catch (KeyManagementException e) {
        e.printStackTrace();
    }

}

}

您的主要问题是,为了验证证书,必须存在一个可信链(一个可信证书和所有中间证书,直至服务器/叶证书)。但是,大多数SSL/TLS服务器不会向您发送完整的链。有时,您只能获得叶证书(没有中间证书或根证书;您可以在Wireshark流量转储中看到这一点)

其他服务器可能会向您发送叶证书和所有/部分中间证书,但不会发送根证书

在这种情况下,您的本地信任库包含丢失的证书以构建完整的链是至关重要的

根据您的观察,我假设服务器只发送叶证书,而不发送中间证书和根证书。因此,为了成功地进行验证,您的信任库必须将中间证书作为受信任证书包含在内,以使其工作(否则,该证书将丢失)。我建议将根证书和中间证书都包含到您的信任库中


顺便说一句:服务器不发送中间CA证书也可能是服务器配置问题。通常我建议配置服务器以发送叶证书和中间证书。

不清楚您是如何实现证书固定的-编辑您的问题并添加代码。无论如何,如果你实现了代码,你应该知道证书验证是否失败以及为什么失败……我已经用代码更新了帖子。谢谢@Robert的详细解释。这也是我的期望——存储整个证书链以使固定工作。这就是为什么我觉得有点奇怪,当我尝试在没有叶证书和根证书的情况下锁定中间证书时,它仍然在进行身份验证,没有例外。以下是证书链的屏幕截图(我相信服务器正在发送整个证书链):!。你知道这种行为吗?