Добавление самозаверяющего сертификата OkHttpClient

#java #android #ssl #certificate

#java #Android #ssl #сертификат

Вопрос:

У меня есть приложение для Android, которому необходимо подключиться к серверу с помощью REST. Я использую Retrofit 2 для запросов, и это работает хорошо. Проблема в том, что я хочу использовать SSL-соединение. При открытом ssl у меня есть client.crt, myPrivateKey.pem и request.csr. У меня также есть RootCA, который я использовал для шифрования сертификата клиента и сервера.

Когда я проверяю онлайн, я нахожу множество решений с файлами одного CA.

Это код, который у меня есть на данный момент.

 // https://developer.android.com/training/articles/security-ssl.html#java
private OkHttpClient initClient(boolean ssl) {
    if (ssl) {
        SSLSocketFactory sslSocketFactory = null;
        X509TrustManager x509TrustManager = null;
        try {
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            InputStream certificateFileCRT = mContext.getResources().openRawResource(R.raw.client);
            Certificate certCRT = cf.generateCertificate(certificateFileCRT);
            System.out.println("ca="   ((X509Certificate) certCRT).getSubjectDN());
            certificateFileCRT.close();

            String keyStoreType = KeyStore.getDefaultType();
            KeyStore keyStore = KeyStore.getInstance(keyStoreType);
            keyStore.load(null, null);
            keyStore.setCertificateEntry("ca", certCRT);

            String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
            tmf.init(keyStore);

            TrustManager[] trustManagers = tmf.getTrustManagers();
            x509TrustManager = (X509TrustManager) trustManagers[0];

            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, new TrustManager[]{x509TrustManager}, null);

            sslSocketFactory = sslContext.getSocketFactory();
        } catch (CertificateException |IOException | KeyStoreException | NoSuchAlgorithmException | KeyManagementException e) {
            e.printStackTrace();
        }

        return new OkHttpClient.Builder()
                .readTimeout(60, TimeUnit.SECONDS)
                .sslSocketFactory(sslSocketFactory, x509TrustManager)
                .build();
        // return getUnsafeOkHttpClient();
    } else {
        return new OkHttpClient.Builder()
                .readTimeout(60, TimeUnit.SECONDS)
                .build();
    }
}
  

Когда я отправляю запрос клиенту, я получаю java.security.cert.CertPathValidatorException привязка доверия для пути сертификации не найдена.

Не могли бы вы, пожалуйста, помочь мне создать мой клиент с моим сертификатом и моим ключом!

Ответ №1:

Я исправил свою кодовую базу с этого веб-сайта

частный OkHttpClient initClient() вызывает исключение KeyStoreException, CertificateException, исключение NoSuchAlgorithmException, исключение IOException, исключение UnrecoverableKeyException, исключение KeyManagementException {

 // Trust self signed certificate
InputStream certificateFileCRT = mContext.getResources().openRawResource(R.raw.server);
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) certificateFactory.generateCertificate(certificateFileCRT);
String alias = cert.getSubjectX500Principal().getName();
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null);
trustStore.setCertificateEntry(alias, cert);

// KeyStore containing client certificate
KeyStore keyStore = KeyStore.getInstance("PKCS12");
InputStream fis = mContext.getResources().openRawResource(R.raw.client);
keyStore.load(fis, "PASSWORD".toCharArray());

// Build an SSL context
KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
kmf.init(keyStore, "PASSWORD".toCharArray());
KeyManager[] keyManagers = kmf.getKeyManagers();
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init(trustStore);
TrustManager[] trustManagers = tmf.getTrustManagers();

SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(keyManagers, trustManagers, null);

return new OkHttpClient.Builder()
        .readTimeout(60, TimeUnit.SECONDS)
        .sslSocketFactory(sslContext.getSocketFactory())
        .hostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        })
        .build();               
  

}