javax.net.ssl.SSLHandshakeException:收到致命警报:unknown_ca

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28958514/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 07:05:47  来源:igfitidea点击:

javax.net.ssl.SSLHandshakeException: Received fatal alert: unknown_ca

javasslkeystoreself-signedtruststore

提问by Stine

I have to connect to a server via SSL dual authentication. I have added my own private key plus certificate to a keystore.jksand the self signed certificate of the server to a truststore.jks, both files are copied to /usr/share/tomcat7. The socket factory used by my code is delivered by the following provider:

我必须通过 SSL 双重身份验证连接到服务器。我已将自己的私钥和证书添加到keystore.jks并将服务器的自签名证书添加到truststore.jks,这两个文件都被复制到 /usr/share/tomcat7。我的代码使用的套接字工厂由以下提供程序提供:

@Singleton
public static class SecureSSLSocketFactoryProvider implements Provider<SSLSocketFactory> {
    private SSLSocketFactory sslSocketFactory;

    public SecureSSLSocketFactoryProvider() throws RuntimeException {
        try {
            final KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            final InputStream trustStoreFile = new FileInputStream("/usr/share/tomcat7/truststore.jks");
            trustStore.load(trustStoreFile, "changeit".toCharArray());
            final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(trustStore);

            final KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            final InputStream keyStoreFile = new FileInputStream("/usr/share/tomcat7/keystore.jks");
            keyStore.load(keyStoreFile, "changeit".toCharArray());
            final KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            keyManagerFactory.init(keyStore, "changeit".toCharArray());

            final SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);

            this.sslSocketFactory = sslContext.getSocketFactory();

        } catch (final KeyStoreException e) {
            Log.error("Key store exception: {}", e.getMessage(), e);
        } catch (final CertificateException e) {
            Log.error("Certificate exception: {}", e.getMessage(), e);
        } catch (final UnrecoverableKeyException e) {
            Log.error("Unrecoverable key exception: {}", e.getMessage(), e);
        } catch (final NoSuchAlgorithmException e) {
            Log.error("No such algorithm exception: {}", e.getMessage(), e);
        } catch (final KeyManagementException e) {
            Log.error("Key management exception: {}", e.getMessage(), e);
        } catch (final IOException e) {
            Log.error("IO exception: {}", e.getMessage(), e);
        }
    }

    @Override
    public SSLSocketFactory get() {
        return sslSocketFactory;
    }
}

When I try to connect to an endpoint on the server I get the following exception though:

当我尝试连接到服务器上的端点时,我收到以下异常:

javax.net.ssl.SSLHandshakeException: Received fatal alert: unknown_ca
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) ~[na:1.7.0_45]
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:154) ~[na:1.7.0_45]
    at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1959) ~[na:1.7.0_45]
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1077) ~[na:1.7.0_45]
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312) ~[na:1.7.0_45]
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339) ~[na:1.7.0_45]
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323) ~[na:1.7.0_45]
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563) ~[na:1.7.0_45]
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185) ~[na:1.7.0_45]
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153) ~[na:1.7.0_45]

Any idea what I have missed here?

知道我在这里错过了什么吗?

采纳答案by Steffen Ullrich

If you get an alert unknown_caback from the server, then the server did not like the certificate you've send as the client certificate, because it is not signed by a CA which is trusted by the server for client certificates.

如果您unknown_ca从服务器收到警报,则服务器不喜欢您作为客户端证书发送的证书,因为它不是由服务器信任的客户端证书的 CA 签署的。