没有对等证书异常 - 具有自签名证书的Volley和Android [英] No peer certificate Exception - Volley and Android with self signed certificate

查看:163
本文介绍了没有对等证书异常 - 具有自签名证书的Volley和Android的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试让我的应用通过https与我的服务器通信。
由于我不想付费以获得由受信任的CA签署的服务器证书,因此解决方案是使用自签名证书。

I'm trying to make my app communicate with my server via https. As I don't want to pay to get my server certificate signed by a trusted CA, the solution is to use a self signed certificate.

所以,我创建了我的caconfig.cnf如下:

So, I've created my caconfig.cnf as follows:

[ ca ]
default_ca              = CA_default                    # The default ca section

[ CA_default ]
dir                     = ./demoCA                      # top dir
database                = $dir/index.txt                # index file.
new_certs_dir           = $dir/newcerts                 # new certs dir

certificate             = $dir/cacert.pem               # The CA cert
serial                  = $dir/serial                   # serial no file
private_key             = $dir/private/cakey.pem        # CA private key
RANDFILE                = $dir/private/.rand            # random number file

default_days            = 365                           # how long to certify for
default_crl_days        = 30                            # how long before next CRL
default_md              = md5                           # md to use
policy                  = policy_any                    # default policy
email_in_dn             = no                            # Don't add the email into cert DN
name_opt                = ca_default                    # Subject name display option
cert_opt                = ca_default                    # Certificate display option
copy_extensions         = none                          # Don't copy extensions from request

[ policy_any ]
countryName             = optional
stateOrProvinceName     = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

然后,我使用以下命令创建并签署了我的证书:

Then, I've created and signed my certificate using the following commands:

$ mkdir myCA myCA/private myCA/newcerts
$ echo "01" > myCA/serial
$ touch demoCA/index.txt

$ openssl genrsa -des3 -out myCA/private/cakey.pem 1024
$ openssl req -new -x509 -days 3650 -key myCA/private/cakey.pem -out myCA/cacert.pem

$ openssl req -sha1 -newkey rsa:2048 -keyout server-key.pem -out server-cert-req.pem -subj '/CN=myhost/' -nodes
$ openssl ca -config caconfig.cnf -in server-cert-req.pem -out server-cert.pem
$ openssl x509 -inform PEM -in cacert.pem -outform DER -out certificate.cer
$ rm server-cert-req.pem

在我的nodejs服务器代码中,我正在创建这样的https服务器:

In my nodejs server code, I'm creating the https server like this:

var express = require('express');
var https = require('https');

var PORT = 443;
var app = express();

app.get('/', function (req, res) {
    res.send("Server is working");
});

var httpsOptions = {
    key: fs.readFileSync('server-key.pem'),
    cert: fs.readFileSync('server-cert.pem')
};

https.createServer(httpsOptions, app).listen(PORT, function() {
    console.log('%s: Node server started on port %d ...', Date(Date.now() ), PORT);
});

为了测试一切是否正确,我还创建了一个节点客户端脚本,请求我的服务器。以下是我的节点客户端的代码:

In order to test if everything is correct, I've also created a node client script, which makes a request to my server. Here is the code for my node client:

var https = require('https');
var fs = require('fs');

var request = https.request({
    host: 'myhost',
    port: 443,
    path: '/',
    method: 'GET',
    rejectUnauthorized: true,

    // Once it is self signed, I'm using my server certificate (public key).
    ca: [fs.readFileSync('cacert.pem').toString()]
}, function(response) {
    response.on('data', function(data) {
        console.log(data.toString());
    });
});

request.on('error', function(err) {
    console.log(err);
})

request.end();

当我运行我的节点客户端脚本时,它运行正常。另一方面,我用来检查Volley如何使用https的Android Volley Examples应用程序无效。下面,我将描述为了尝试使其工作而遵循的所有步骤。

When I run my node client script, it works perfectly. On the other hand, the Android Volley Examples app, which I'm using to check how Volley works with https, is not working. Below, I'm describing all the steps I've followed in order to try to make it work.

我使用certificate.cer创建了一个.bks文件使用以下命令的文件:

I've created a .bks file using my certificate.cer file using the following command:

keytool -importcert -v -trustcacerts -file "certificate.cer" -alias IntermediateCA -keystore "res/raw/my_keystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-146.jar" -storetype BKS -storepass mysecret

然后,我已经验证证书是否正确导入到.bks中,如下所示:

Then, I've verified if the certificate was imported correctly into the .bks as follows:

keytool -list -keystore "res/raw/my_keystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-146.jar" -storetype BKS -storepass mysecret

我得到以下输出,这意味着它是正确的:

And I got the following output, that means it's correct:

Keystore type: BKS
Keystore provider: BC

Your keystore contains 1 entry

imeto_alias, Oct 16, 2014, trustedCertEntry, 
Certificate fingerprint (SHA1): 03:DC:A1:6A:9B:1D:AD:59:A9:9B:1F:C2:43:7E:80:07:3B:B6:BE:CB

我遇到过这个教程,当我使用Volley时,我决定遵循它。所以,下面是我对示例项目所做的以下更改。

I've came across to this tutorial, and, as I'm using Volley, I've decided to follow it. So, below are the following changes I've made to the example project.

Got Volley from git clone https://android.googlesource.com/platform/frameworks/volley

Got Android Volley Examples project from git clone git://github.com/ogrebgr/android_volley_examples.git

Copied my_keystore.bks containing the self-signed public key in res/raw;

Opened Act_SsSslHttpClient in the examples project, found "R.raw.test" and replaced it with R.raw.my_keystore;

Found "new SslHttpClient(" and replaced the default password "test123″ with "mysecret";

Replaced "44400" with the HTTPS port of my server/virtualhost ("443"). (I could also remove this parameter since "443" is the default port;

Replaced "https://tp.bolyartech.com:44400/https_test.html" with my server URL.

Started the app, went to "HTTPS with self-signed cert", then "Execute HTTPS request"

但是,当我按下按钮时,我得到以下异常:

But, when I pressed the button, I got the following exception:

javax.net.ssl.SSLPeerUnverifiedException: No peer certificate

下面是我的JavaCode ...

Below, is my JavaCode...

public class Act_SsSslHttpClient extends Activity {
    private TextView mTvResult;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.act__ss_ssl_http_client);

        mTvResult = (TextView) findViewById(R.id.tv_result);

        Button btnSimpleRequest = (Button) findViewById(R.id.btn_simple_request);
        btnSimpleRequest.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {

                // Replace R.raw.test with your keystore 
                InputStream keyStore = getResources().openRawResource(R.raw.my_keystore);


                // Usually getting the request queue shall be in singleton like in {@seeAct_SimpleRequest}
                // Current approach is used just for brevity
                RequestQueue queue = Volley.newRequestQueue(Act_SsSslHttpClient.this,
                                     new ExtHttpClientStack(new SslHttpClient(keyStore,
                                         "mysecret")));

                StringRequest myReq = new StringRequest(Method.GET,
                                                    "https://myServerURL/",
                                                    createMyReqSuccessListener(),
                                                    createMyReqErrorListener());

                queue.add(myReq);
            }
        });
    }

...

}

有人知道解决方案吗?
谢谢。

Does anybody know the solution? Thank you.

推荐答案

我在我的测试环境中使用自签名证书。为了使它工作,我在onCreate方法的Application类中调用此方法。它使所有证书都被接受。它不是保存,但出于测试目的是可以的。

I am using self signed certificate in my test environment. To make it work I call this method in my Application class in onCreate method. It makes all certificates accepted. It is not save, but for test purposes is ok.

@Override
public void onCreate() {
    nuke();
    super.onCreate();
}

public static void nuke() {
    try {
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                X509Certificate[] myTrustedAnchors = new X509Certificate[0];
                return myTrustedAnchors;
            }

            @Override
            public void checkClientTrusted(X509Certificate[] certs,
                    String authType) {}

            @Override
            public void checkServerTrusted(X509Certificate[] certs,
                    String authType) {}
        } };

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new SecureRandom());
        HttpsURLConnection
                .setDefaultSSLSocketFactory(sc.getSocketFactory());
        HttpsURLConnection
                .setDefaultHostnameVerifier(new HostnameVerifier() {

                    @Override
                    public boolean verify(String arg0, SSLSession arg1) {
                        return true;
                    }
                });
    } catch (Exception e) {}
}

这篇关于没有对等证书异常 - 具有自签名证书的Volley和Android的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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