Restlet javax.net.ssl.SSLHandshakeException:证书链为null [英] Restlet javax.net.ssl.SSLHandshakeException: null cert chain

查看:133
本文介绍了Restlet javax.net.ssl.SSLHandshakeException:证书链为null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在本地测试客户端和服务器之间的SSL通信. 因此,我使用OpenSSL命令生成了证书.在cacert文件中添加了此证书.还生成了.p12文件.

I am testing SSL communication between client and server locally. So I generated certificate using OpenSSL commands. Added this certificate in cacert file. Also generated .p12 file.

我在服务器和客户端中使用相同的.p12文件. 这是服务器代码

I am using the same .p12 file in server and client. This is the server code

Server server = component.getServers().add(Protocol.HTTPS, port);
Series<Parameter> params = server.getContext().getParameters();

params.add("keystorePath", ".p12 file path");
params.add("keystoreType", "PKCS12");
params.add("needClientAuthentication","true");

component.getDefaultHost().attach("", "/AA"), new AAClass());
component.start();

这是客户代码:

Client client = trustAllCerts();
clientResource = new ClientResource(url);
clientResource.setNext(client);
try{
      clientText = clientResource.post"");
 }
 catch(ResourceException e){
    e.printStackTrace();
 }

public Client trustAllCerts() {
    Client client = null;
    try {
        client = new Client(new Context(), Protocol.HTTPS);
        Context context = client.getContext();


        final SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
        context.getAttributes().put("sslContextFactory", new SslContextFactory() {
            public void init(Series<Parameter> parameters) {

            }

            public SSLContext createSslContext() {
                return sslContext;
            }
        });
        TrustManager tm = new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
        context.getAttributes().put("hostnameVerifier", new HostnameVerifier() {                
            @Override
            public boolean verify(String arg0, SSLSession arg1) {
                return true;
            }

        });         

        sslContext.init(null, new TrustManager[] { tm }, null);         

    } catch (KeyManagementException e) {
        LOGGER.error("Exception in Key Management" + e);
    } catch (NoSuchAlgorithmException e) {
        LOGGER.error("Exception in Algorithm Used" + e);
    }
    return client;
}

我遇到以下异常:

Restlet-1299242, fatal error: 42: null cert chain
javax.net.ssl.SSLHandshakeException: null cert chain
%% Invalidated:  [Session-25, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256]
Restlet-1299242, SEND TLSv1.2 ALERT:  fatal, description = bad_certificate
Restlet-1299242, WRITE: TLSv1.2 Alert, length = 2
Restlet-1299242, fatal: engine already closed.  Rethrowing javax.net.ssl.SSLHandshakeException: null cert chain
Restlet-1299242, called closeInbound()
Restlet-1299242, fatal: engine already closed.  Rethrowing javax.net.ssl.SSLException: Inbound closed before receiving peer's close_notify: possible truncation attack?
Restlet-1299242, called closeOutbound()
Restlet-1299242, closeOutboundInternal()

我尝试使用System.setProperty()添加密钥库和信任库,但是没有用.

I tried to add keystore and truststore using System.setProperty() but it didn't work.

请帮助.预先感谢.

推荐答案

首先,让我们创建一个JKS格式的密钥库. PKCS12通常在浏览器中使用,并且在默认的Java应用程序中使用JKS(据我所知). Java也支持PKCS12,但我不知道确切的参数.

First, lets create a JKS formatted keystore. PKCS12 is usually used in browser and on default java applications uses JKS (as far as I know). Java also supports PKCS12 but I do not know exact parameters for it.

准备JKS文件

让我们在PKCS12文件中查找并获取我们要提取JKS文件的证书别名.

Lets look in our PKCS12 file and get the certificate aliases that we want to extract our JKS file.

keytool -list \
        -keystore [*.p12 file] \
        -storepass [password] \
        -storetype PKCS12 \
        -v

请注意要导出的别名.现在让我们创建一个JKS文件.

Note the aliases you want to export. And now lets create a JKS file.

keytool -keystore [*.jks file path] -genkey -alias client

这会问很多问题.您可以根据需要填充它们.现在,您可以将别名从* .p12文件导出到* .jks文件.

This will ask bunch of questions. You can fill them as you like. Now, you can export your aliases from *.p12 file to *.jks file.

keytool -importkeystore \
        -srckeystore [*.p12 file path] \
        -srcstoretype pkcs12 \
        -srcalias [alias from first command] \
        -destkeystore [*.jks file path] \
        -deststoretype jks \
        -deststorepass [*.jks file password] \
        -destalias [new alias]

如果您没有任何PKCS12文件,或者您的证书采用CER,DER或PEM格式,则可以使用以下命令将证书添加到密钥库中.

If you do not have any PKCS12 file, or your certificates are in CER, DER or PEM format you can add your certificates to your keystore using the command below.

keytool -import \
        -alias [new alias] \
        -keystore [*.jks file path] \
        -file [*.DER file path]

并且请确保您导入了证书,证书,证书提供者的证书(中间证书)和根证书.

And please be sure that you imported, your certificate, your certificate provider's certificate (intermediate certificate) and root certificate.

现在,您可以检查JKS文件中是否包含所需的所有证书.

Now you can check that your JKS file contains all the certificates you are needed.

keytool -list \
        -keystore [*.jks file path] \
        -storepass [password] \
        -storetype jks \
        -v

设置服务器

您可以在客户端和服务器端使用JKS文件.根据 Restlet文档,您可以使用像这样的JKS文件来提供HTTPS连接.

You can use your JKS file both on client and server side. According to Restlet documentation you can use JKS file like this to provide HTTPS connection.

Server server = component.getServers().add(Protocol.HTTPS, port);  
Series<Parameter> parameters = server.getContext().getParameters();
parameters.add("sslContextFactory","org.restlet.engine.ssl.DefaultSslContextFactory");
parameters.add("keyStorePath", "*.jks file");
parameters.add("keyStorePassword", "password");
parameters.add("keyPassword", "password");
parameters.add("keyStoreType", "JKS");

之后,如果您从浏览器检查端口,则必须看到安全标志.或者,您可以使用一些在线工具(与此类似)来检查您的证书.

After that if you check your port from browser you must see a secure sign. Or you can use some online tool(like this one) to check your certificate.

设置客户端

现在让我们看看客户端.由于您正在开发应用程序的两面,因此可以使用已经创建的JKS文件.

Now lets look at client side. Since you are developing both side of the application you can use already created JKS file.

Context con = new Context();
Series<Parameter> clParameters = con.getParameters();
clParameters.add("truststorePath", "*.jks file");
clParameters.add("truststorePassword", "password");
clParameters.add("truststoreType", "JKS");
Client restletClient = new Client(con, Protocol.HTTPS);

在测试或其他情况下,您的证书主机名和实际主机名可能不匹配.为了禁用主机名检查,您可以将此块添加到您的应用程序中.

While testing or in other circumstances, your certificate hostname and your actual hostname may not match. In order to disable hostname checks you can add this block to your application.

static{
    javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
    new javax.net.ssl.HostnameVerifier(){

        public boolean verify(String hostname,
                javax.net.ssl.SSLSession sslSession ) {
            return true ;
        }
    });
}

一些想法

由于我无法在我的语言环境中对其进行测试,因此我不能完全确定您的客户端JKS文件和服务器JKS文件必须相同.您可能只需要将自己的证书添加到server.jks. SSL和证书对我来说总是很棘手的.经过一些反复试验后,我通常可以使它正常工作.希望对您有帮助.

Since I cannot test it on my locale, I am not exactly sure that your client and server JKS file must be the same. You may only need to add your own certificate to your server.jks. SSL and certificates are always tricky for me. I usually get it work after some trial and error. I hope this will help you.

此外,您可能还需要考虑使用反向代理类型的Web服务器,例如Apache2或Nginx.如果要使用它们,则必须将证书合并到一个文件中.如果您查看证书文件,就会发现每个文件(您自己的证书,中间证书和根证书)都是这样的

Also, You may also want to consider, using a reverse proxy kind of web server like Apache2 or Nginx. If you want to use them, you must merge your certificates to a single file. If you look at your certificate file you see that each file (your own certificate, intermediate certificate and root certificate) is like this

-----BEGIN CERTIFICATE-----
MIIDfTCCAuagAwIBAgIDErvmMA0GCSqGSIb3DQEBBQUA...
....
-----END CERTIFICATE-----

您只需要将一个添加到另一个即可创建合并的证书.并且使用该证书终止Apache2或Nginx上的SSL.这就是我通常要做的.但是在客户端,您仍然需要创建JKS文件.

You need to simply add one to other to create a merged certificate. And than use that certificate to end SSL on Apache2 or Nginx. This is what I usually do. But on client side you still need to create JKS files.

这篇关于Restlet javax.net.ssl.SSLHandshakeException:证书链为null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆