Description:
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
implementation 'io.reactivex.rxjava3:rxjava:3.0.10'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
public class X509Impl implements X509KeyManager {
private final String alias;
private final X509Certificate[] certChain;
private final PrivateKey privateKey;
public static SSLContext setForConnection(HttpsURLConnection con, Context context, String alias) throws CertificateException, KeyManagementException {
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("TLS");
} catch(NoSuchAlgorithmException e){
throw new RuntimeException("Should not happen...", e);
}
sslContext.init(new KeyManager[] { fromAlias(context, alias)}, null, null);
con.setSSLSocketFactory(sslContext.getSocketFactory());
return sslContext;
}
public static X509Impl fromAlias(Context context, String alias) throws CertificateException {
X509Certificate[] certChain;
PrivateKey privateKey;
try {
certChain = KeyChain.getCertificateChain(context, alias);
privateKey = KeyChain.getPrivateKey(context, alias);
} catch (KeyChainException e) {
throw new CertificateException(e);
} catch (InterruptedException e) {
throw new CertificateException(e);
}
if(certChain == null || privateKey == null){
throw new CertificateException("Can't access certificate from keystore");
}
return new X509Impl(alias, certChain, privateKey);
}
public X509Impl(String alias, X509Certificate[] certChain, PrivateKey privateKey) throws CertificateException {
this.alias = alias;
this.certChain = certChain;
this.privateKey = privateKey;
}
@Override
public String chooseClientAlias(String[] arg0, Principal[] arg1, Socket arg2) {
return alias;
}
@Override
public X509Certificate[] getCertificateChain(String alias) {
if(this.alias.equals(alias)) return certChain;
return null;
}
@Override
public PrivateKey getPrivateKey(String alias) {
if(this.alias.equals(alias)) return privateKey;
return null;
}
// Methods unused (for client SSLSocket callbacks)
@Override public final String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
throw new UnsupportedOperationException();
}
@Override public final String[] getClientAliases(String keyType, Principal[] issuers) {
throw new UnsupportedOperationException();
}
@Override public final String[] getServerAliases(String keyType, Principal[] issuers) {
throw new UnsupportedOperationException();
}
}
@io.reactivex.rxjava3.annotations.NonNull BehaviorSubject<String> subject = BehaviorSubject.create();
KeyChain.choosePrivateKeyAlias(requireActivity(), new KeyChainAliasCallback() {
@Override
public void alias(@Nullable String alias) {
System.out.println(alias);
subject.onNext(alias);
}
}, null, null, null, -1, null);
subject
.observeOn(Schedulers.io())
.map(it->{
X509Certificate[] certChain = KeyChain.getCertificateChain(requireContext(), it);
PrivateKey certKey = KeyChain.getPrivateKey(requireContext(), it);
TrustManagerFactory trustManager = TrustManagerFactory.getInstance("X509");
KeyStore ks = KeyStore.getInstance("AndroidCAStore");
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null,null);
if (ks != null) {
ks.load(null, null);
Enumeration<String> aliases = ks.aliases();
while (aliases.hasMoreElements()) {
String alias = (String) aliases.nextElement();
X509Certificate cert = (X509Certificate) ks.getCertificate(alias);
trustStore.setCertificateEntry(alias, cert);
//To print all certs
System.out.println(cert.getIssuerDN().getName());
}
}
trustManager.init(trustStore);
X509Impl x509 = new X509Impl(it, certChain, certKey);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(new KeyManager[]{x509}, trustManager.getTrustManagers(), null);
OkHttpClient.Builder builer = new OkHttpClient.Builder();
TrustManager[] ms = trustManager.getTrustManagers();
builer.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) ms[0]);
return builer.build();
})
.map(it->{
OkHttpClient client = it;
Request request = new Request.Builder()
.url("https://www.dextro.link")
.build();;
Response response = client.newCall(request).execute();
return response;
})
.subscribe()
;