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.