0

hi I'm working since 2 week on this problem but no luck. Its been a long time i trying every solution on stack over flow but didn't found any help Today I'm sharing my code and approach. I am creating a remote control device for android mobiles to connect android TV with device. I'm using these libraries

    implementation("org.bouncycastle:bcpkix-jdk15on:1.70")
    implementation("com.google.protobuf:protobuf-java:3.21.7")
    implementation("com.squareup.okhttp3:okhttp:4.10.0")
    implementation("com.squareup.okio:okio:3.2.0")
    implementation("com.github.ConnectSDK:Connect-SDK-Android:master-SNAPSHOT")

I'm using keystore to generate key manager and trust manager and polo library is also included into my project. here is the code for trust manager

import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;

import com.jas.universaltvremote.polo.ssl.SslUtil;

import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import java.util.Locale;
import java.util.UUID;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import javax.security.auth.x500.X500Principal;
/* loaded from: classes4.dex */
public final class KeyStoreManager {
    private static String ANDROID_KEYSTORE = "AndroidKeyStore";
    private static final boolean DEBUG = false;
    private static final String KEYSTORE_FILENAME = "androidtv.keystore";
    private static final char[] KEYSTORE_PASSWORD = "KeyStore_Password".toCharArray();
    private static final String LOCAL_IDENTITY_ALIAS = "androidtv-remote";
    private static final String REMOTE_IDENTITY_ALIAS_PATTERN = "androidtv-remote-%s";
    private static final String SERVER_IDENTITY_ALIAS = "androidtv-local";
    private static final String TAG = "KeyStoreManager";
    private final Context mContext;
    private DynamicTrustManager mDynamicTrustManager;
    private KeyStore mKeyStore;

    /* loaded from: classes4.dex */
    public static class DynamicTrustManager implements X509TrustManager {
        private X509TrustManager trustManager;

        @Override // javax.net.ssl.X509TrustManager
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }

        public DynamicTrustManager(KeyStore keyStore) {
            reloadTrustManager(keyStore);
        }

        @Override // javax.net.ssl.X509TrustManager
        public void checkClientTrusted(X509Certificate[] x509CertificateArr, String str) throws CertificateException {
            this.trustManager.checkClientTrusted(x509CertificateArr, str);
        }

        @Override // javax.net.ssl.X509TrustManager
        public void checkServerTrusted(X509Certificate[] x509CertificateArr, String str) throws CertificateException {
            this.trustManager.checkServerTrusted(x509CertificateArr, str);
        }

        public void reloadTrustManager(KeyStore keyStore) {
            try {
                TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                trustManagerFactory.init(keyStore);
                TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
                for (int i = 0; i < trustManagers.length; i++) {
                    if (trustManagers[i] instanceof X509TrustManager) {
                        this.trustManager = (X509TrustManager) trustManagers[i];
                        return;
                    }
                }
                throw new IllegalStateException("No trust manager found");
            } catch (KeyStoreException | NoSuchAlgorithmException unused) {
            }
        }
    }

    public KeyStoreManager(Context context) {
        this.mContext = context;
        KeyStore load = load();
        this.mKeyStore = load;
        this.mDynamicTrustManager = new DynamicTrustManager(load);
    }

    private void clearKeyStore() {
        try {
            Enumeration<String> aliases = this.mKeyStore.aliases();
            while (aliases.hasMoreElements()) {
                this.mKeyStore.deleteEntry(aliases.nextElement());
            }
        } catch (KeyStoreException unused) {
        }
        store();
    }

    private static String createAlias(String str) {
        return String.format(REMOTE_IDENTITY_ALIAS_PATTERN, str);
    }

    private void createIdentity(KeyStore keyStore) throws GeneralSecurityException {
        createIdentity(keyStore, SERVER_IDENTITY_ALIAS);
    }

    private void createIdentity(KeyStore keyStore, String str) throws GeneralSecurityException {
        createIdentity(keyStore, str, getUniqueId());
    }

    private void setLocale(Locale locale) {
        try {
            Locale.setDefault(locale);
            Resources resources = this.mContext.getResources();
            Configuration configuration = resources.getConfiguration();
            configuration.locale = locale;
            resources.updateConfiguration(configuration, resources.getDisplayMetrics());
        } catch (Exception unused) {
        }
    }

    private void createIdentity(KeyStore keyStore, String str, String str2) throws GeneralSecurityException {
        KeyPair generateKeyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
        try {
            keyStore.setKeyEntry(str, generateKeyPair.getPrivate(), null, new Certificate[]{SslUtil.generateX509V3Certificate(generateKeyPair, getCertificateName(str2))});
        } catch (IllegalArgumentException unused) {
            Locale locale = Locale.getDefault();
            setLocale(Locale.ENGLISH);
            keyStore.setKeyEntry(str, generateKeyPair.getPrivate(), null, new Certificate[]{SslUtil.generateX509V3Certificate(generateKeyPair, getCertificateName(str2))});
            setLocale(locale);
        }
    }

    private KeyStore createIdentityKeyStore() throws GeneralSecurityException {
        KeyStore keyStore;
        if (!useAndroidKeyStore()) {
            keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            try {
                keyStore.load(null, KEYSTORE_PASSWORD);
            } catch (IOException e) {
                throw new GeneralSecurityException("Unable to create empty keyStore", e);
            }
        } else {
            keyStore = KeyStore.getInstance(ANDROID_KEYSTORE);
            try {
                keyStore.load(null);
            } catch (IOException e2) {
                throw new GeneralSecurityException("Unable to create empty keyStore", e2);
            }
        }
        createIdentity(keyStore);
        return keyStore;
    }

    private static final String getCertificateName() {
        return getCertificateName(getUniqueId());
    }

    private static final String getCertificateName(String str) {
        return "CN=androidtv/" + (Build.PRODUCT + "/" + Build.DEVICE + "/" + Build.MODEL + "/" + str).replace("+", "(Plus)").replace("=", "-eq-");
    }

    private static String getSubjectDN(Certificate certificate) {
        X500Principal subjectX500Principal;
        if (!(certificate instanceof X509Certificate) || (subjectX500Principal = ((X509Certificate) certificate).getSubjectX500Principal()) == null) {
            return null;
        }
        return subjectX500Principal.getName();
    }

    private static final String getUniqueId() {
        if (!TextUtils.isEmpty(Build.SERIAL)) {
            return Build.SERIAL;
        }
        String address = BluetoothAdapter.getDefaultAdapter().getAddress();
        return TextUtils.isEmpty(address) ? UUID.randomUUID().toString() : address;
    }

    private boolean hasServerIdentityAlias(KeyStore keyStore) {
        try {
            return keyStore.containsAlias(SERVER_IDENTITY_ALIAS);
        } catch (KeyStoreException unused) {
            return false;
        }
    }

    private KeyStore load() {
        KeyStore keyStore;
        KeyStore keyStore2 = null;
        try {
            if (!useAndroidKeyStore()) {
                keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
                keyStore.load(this.mContext.openFileInput(KEYSTORE_FILENAME), KEYSTORE_PASSWORD);
            } else {
                keyStore = KeyStore.getInstance(ANDROID_KEYSTORE);
                keyStore.load(null);
            }
            keyStore2 = keyStore;
        } catch (KeyStoreException e) {
            throw new IllegalStateException("Unable to get default instance of KeyStore", e);
        } catch (IOException | GeneralSecurityException unused) {
        }
        if (keyStore2 == null || !hasServerIdentityAlias(keyStore2)) {
            try {
                KeyStore createIdentityKeyStore = createIdentityKeyStore();
                store(createIdentityKeyStore);
                return createIdentityKeyStore;
            } catch (GeneralSecurityException e2) {
                throw new IllegalStateException("Unable to create identity KeyStore", e2);
            }
        }
        return keyStore2;
    }

    private void store(KeyStore keyStore) {
        if (!useAndroidKeyStore()) {
            try {
                FileOutputStream openFileOutput = this.mContext.openFileOutput(KEYSTORE_FILENAME, 0);
                keyStore.store(openFileOutput, KEYSTORE_PASSWORD);
                openFileOutput.close();
            } catch (IOException e) {
                throw new IllegalStateException("Unable to store keyStore", e);
            } catch (GeneralSecurityException e2) {
                throw new IllegalStateException("Unable to store keyStore", e2);
            }
        }
    }

    private boolean useAndroidKeyStore() {
        return Build.VERSION.SDK_INT >= 18;
    }

    public void clear() {
        clearKeyStore();
        try {
            createIdentity(this.mKeyStore);
        } catch (GeneralSecurityException unused) {
        }
        store();
    }

    public KeyManager[] getKeyManagers() throws GeneralSecurityException {
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(this.mKeyStore, "".toCharArray());
        return keyManagerFactory.getKeyManagers();
    }

    public TrustManager[] getTrustManagers() throws GeneralSecurityException {
        try {
            return new DynamicTrustManager[]{this.mDynamicTrustManager};
        } catch (Exception e) {
            throw new GeneralSecurityException(e);
        }
    }

    public boolean hasServerIdentityAlias() {
        return hasServerIdentityAlias(this.mKeyStore);
    }

    public void initializeKeyStore() {
        initializeKeyStore(getUniqueId());
    }

    public void initializeKeyStore(String str) {
        try {
            createIdentity(this.mKeyStore, LOCAL_IDENTITY_ALIAS, str);
            store();
        } catch (GeneralSecurityException e) {
            throw new IllegalStateException("Unable to create identity KeyStore", e);
        }
    }

    public Certificate removeCertificate(String str) {
        try {
            String createAlias = createAlias(str);
            if (!this.mKeyStore.containsAlias(createAlias)) {
                return null;
            }
            Certificate certificate = this.mKeyStore.getCertificate(createAlias);
            this.mKeyStore.deleteEntry(createAlias);
            store();
            return certificate;
        } catch (KeyStoreException unused) {
            return null;
        }
    }

    public void store() {
        this.mDynamicTrustManager.reloadTrustManager(this.mKeyStore);
        store(this.mKeyStore);
    }

    public void storeCertificate(Certificate certificate) {
        storeCertificate(certificate, Integer.toString(certificate.hashCode()));
    }

    public void storeCertificate(Certificate certificate, String str) {
        try {
            String createAlias = createAlias(str);
            String subjectDN = getSubjectDN(certificate);
            if (this.mKeyStore.containsAlias(createAlias)) {
                this.mKeyStore.deleteEntry(createAlias);
            }
            if (subjectDN != null) {
                Enumeration<String> aliases = this.mKeyStore.aliases();
                while (aliases.hasMoreElements()) {
                    String nextElement = aliases.nextElement();
                    String subjectDN2 = getSubjectDN(this.mKeyStore.getCertificate(nextElement));
                    if (subjectDN2 != null && subjectDN2.equals(subjectDN)) {
                        Log.d(TAG, "Deleting entry for " + nextElement + " (" + subjectDN2 + ")");
                        this.mKeyStore.deleteEntry(nextElement);
                    }
                }
            }
            this.mKeyStore.setCertificateEntry(createAlias, certificate);
            store();
        } catch (KeyStoreException unused) {
        }
    }
}

When I attempt to connect with TV, I got error or hand shaking in this snippet

public void attemptToConnect(String str, int i) {
        KeyManager[] keyManagerArr = new KeyManager[0];
        try {
            keyManagerArr = this.keyStoreManager.getKeyManagers();
        } catch (GeneralSecurityException unused) {
        }
        TrustManager[] trustManagerArr = new TrustManager[0];
        try {
            trustManagerArr = this.keyStoreManager.getTrustManagers();
        } catch (GeneralSecurityException unused2) {
        }
        try {
            HttpsTrustManager.allowAllSSL();
            SSLContext context= SSLContext.getInstance("TLS");
             context.init(keyManagerArr, trustManagerArr, new SecureRandom());
            SSLSocket sSLSocket = (SSLSocket)  context.getSocketFactory().createSocket(str, i);
            sSLSocket.setNeedClientAuth(true);
            sSLSocket.setUseClientMode(true);
            sSLSocket.setKeepAlive(true);
            sSLSocket.setTcpNoDelay(true);
            sSLSocket.startHandshake();
            this.sslsock = sSLSocket;
            try {
                this.mInputStream = sSLSocket.getInputStream();
                this.mOutputStream = this.sslsock.getOutputStream();
                Thread thread = new Thread(this.mSocketListener);
                this.mListeningThread = thread;
                thread.start();
                this.commands.clear();
                startReceiveThread();
                ConnectionListener connectionListener = this.listener;
                if (connectionListener != null) {
                    connectionListener.onConnected();
                }
                if (this.isNewAndroidTV) {
                    return;
                }
                sendConfiguration();
            } catch (Exception unused3) {
            }
        } catch (SSLException unused4) {
            attemptToPair(str, i + 1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

got that error

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

Then I tried that trust manager

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class HttpsTrustManager implements X509TrustManager {

    public static TrustManager[] trustManagers;
    private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {};

    @Override
    public void checkClientTrusted(
            java.security.cert.X509Certificate[] x509Certificates, String s)
            throws java.security.cert.CertificateException {

    }

    @Override
    public void checkServerTrusted(
            java.security.cert.X509Certificate[] x509Certificates, String s)
            throws java.security.cert.CertificateException {

    }

    public boolean isClientTrusted(X509Certificate[] chain) {
        return true;
    }

    public boolean isServerTrusted(X509Certificate[] chain) {
        return true;
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return _AcceptedIssuers;
    }
    public static SSLContext context;
    public static void allowAllSSL() {
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {

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

        });

          context = null;
        if (trustManagers == null) {
            trustManagers = new TrustManager[] {
                    new HttpsTrustManager()
            };

        }

        try {
            context = SSLContext.getInstance("TLS");
            context.init(null, trustManagers, new SecureRandom());
        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            e.printStackTrace();
        }

        HttpsURLConnection.setDefaultSSLSocketFactory(context
                .getSocketFactory());
    }

}

Then handshaking problem resolved and on connection successful when i send keypress value then socket throws exception: Broken Pipes. please help me.

0 Answers0