Сертификат клиента не найден android 9 - PullRequest
0 голосов
/ 07 февраля 2020

У меня возникли проблемы с приложением при регистрации на Android 9.

Приложение работает следующим образом: пользователь вводит свой номер телефона, затем он получает OTP, который будет используется сервером для создания сертификата с CSR, отправленным приложением. Затем сертификат приходит в ответ службы подписи сертификата.

Затем этот сертификат будет использоваться вместе с доверенным сертификатом, включенным в приложение, для связи с серверами

Проблема заключается в том, что это работает на Android 7 и 8, но в Android 9 сертификат клиента явно не подключен, поскольку, когда приложение пытается аутентифицировать, сервер отвечает сообщением об ошибке «Сертификат клиента не предоставлен».

Это это код, который я использую для генерации sslcontext:

public void initializeContext() {
        final String[] PROTOCOLS = new String[]{"TLSv1.2"};

        final String[] CIPHERS = {"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"};

        // get user password and file input stream
        KeyStore keyStore = KeyStoreGestor.getKeyStore(mContext);

        Certificate cert = null;
        try {
            if (keyStore != null) {
                cert = keyStore.getCertificate(Constants.ALIAS_CERTIFICATE); //here's where we load the certificate that comes from the server.
            }
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }

        if (rootTrustManager == null) {
            rootTrustManager = loadRootTrustManager(mContext);
        }

        SSLContext sslcontext = null;
        KeyManagerFactory kmf = null;
        try {
            sslcontext = SSLContext.getInstance("TLSv1.2");
            kmf = KeyManagerFactory.getInstance(
                    KeyManagerFactory.getDefaultAlgorithm()
            );

            if (cert == null) {
                sslcontext.init(null, new TrustManager[]{rootTrustManager}, null);
            } else {
                isLoggedIn = true;
                String password = SharedPreferencesGestor.getKeystorePassword(UnipagosApplication.getMainApplication());
                kmf.init(keyStore, password.toCharArray());
                sslcontext.init(kmf.getKeyManagers(),  new TrustManager[]{rootTrustManager}, null);
            }

        } catch (NoSuchAlgorithmException | UnrecoverableKeyException | KeyManagementException | KeyStoreException e) {
            e.printStackTrace();
        }

        // Allow TLSv1 protocol only
        sslsf = new SSLConnectionSocketFactory(
                sslcontext,
                PROTOCOLS,
                CIPHERS,
                SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        if (httpclient != null) {
            try {
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        httpclient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .build();
    }

Вот где я загружаю доверенный менеджер

private X509TrustManager loadRootTrustManager(Context context) {
        TrustManagerFactory managerFactory = null;
        X509TrustManager tm = null;

        try {
            managerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            managerFactory.init(KeyStoreGestor.loadTrustedKeystore(context));
            TrustManager[] managers = managerFactory.getTrustManagers();

            for (TrustManager tm1 : managers) {
                if (tm1 instanceof X509TrustManager) {
                    tm = (X509TrustManager) tm1;
                    break;
                }
            }
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        return tm;
    }

И вот где я сохраняю сертификат, который приходит с сервера, который, Между прочим, в SignCertificate jsonResponse указывается как строка:

public static synchronized void storeKeyandCertX509(Context context, PrivateKey privateKey, String certificateString) {

        InputStream certificateInputStream = null;
        FileOutputStream keyStoreOutputStream = null;

        try {

            byte[] certificateBytes = Base64.decode(Base64.decode(certificateString, Base64.DEFAULT), Base64.DEFAULT);
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            certificateInputStream = new ByteArrayInputStream(certificateBytes);

            X509Certificate certificateX509 = (X509Certificate)certificateFactory.generateCertificate(certificateInputStream);

            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
            keyPairGenerator.initialize(256);

            keyStore = KeyStore.getInstance(KeyStore.getDefaultType(), keyPairGenerator.getProvider());
            keyStore.load(null,null);

            String passwordString = SharedPreferencesGestor.getKeystorePassword(context);

            X509Certificate[] certChain = new X509Certificate[1];
            certChain[0] =  certificateX509;
            keyStore.setKeyEntry(Constants.ALIAS_PRIVATE_KEY, privateKey, passwordString.toCharArray(),  certChain);
            keyStore.setCertificateEntry(Constants.ALIAS_CERTIFICATE, certificateX509);

            keyStoreOutputStream = context.openFileOutput(Constants.KEY_STORE_FILE_NAME, Context.MODE_PRIVATE);
            keyStore.store(keyStoreOutputStream, passwordString.toCharArray());

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {if (certificateInputStream != null) {certificateInputStream.close();}} catch (IOException e) {e.printStackTrace();}
            try {if (keyStoreOutputStream != null) {keyStoreOutputStream.close();}} catch (IOException e) {e.printStackTrace();}
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            OpenSSL.sharedInstance().initializeContext();
        }
    }
...