Нет сертификата сверстника Исключение - Volley и Android с самозаверяющим сертификатом

Я пытаюсь заставить мое приложение общаться с моим сервером через https. Поскольку я не хочу платить за получение сертификата сервера, подписанного доверенным центром сертификации, решение состоит в том, чтобы использовать самозаверяющий сертификат.

Итак, я создал свой caconfig.cnf следующим образом:

[ 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

Затем я создал и подписал свой сертификат с помощью следующих команд:

$ 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 следующим образом:

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);
});

Чтобы проверить, все ли правильно, я также создал клиентский скрипт узла, который отправляет запрос на мой сервер. Вот код для моего клиента узла:

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();

Когда я запускаю свой клиентский скрипт узла, он работает отлично. С другой стороны, приложение Android Volley examples, которое я использую для проверки работы Volley с https, не работает. Ниже я опишу все шаги, которые я выполнил, чтобы попытаться заставить его работать.

Я создал файл .bks, используя мой файл certificate.cer, используя следующую команду:

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 следующим образом:

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

И я получил следующий вывод, это означает, что это правильно:

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

Я сталкивался с этимруководствои, так как я использую залп, я решил следовать ему. Итак, ниже приведены следующие изменения, которые я внес в пример проекта.

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"

Но, когда я нажал кнопку, я получил следующее исключение:

javax.net.ssl.SSLPeerUnverifiedException: No peer certificate

Ниже мой 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);
            }
        });
    }

...

}

Кто-нибудь знает решение? Спасибо.

Ответы на вопрос(1)

Ваш ответ на вопрос