Last active
June 9, 2022 21:01
-
-
Save HughJeffner/6eac419b18c6001aeadb to your computer and use it in GitHub Desktop.
Trust both system KeyStore and custom KeyStore on Android
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.google.common.collect.ImmutableList; | |
import com.google.common.collect.Iterables; | |
import java.security.KeyStore; | |
import java.security.KeyStoreException; | |
import java.security.NoSuchAlgorithmException; | |
import java.security.cert.CertificateException; | |
import java.security.cert.X509Certificate; | |
import java.util.Arrays; | |
import java.util.List; | |
import javax.net.ssl.SSLContext; | |
import javax.net.ssl.TrustManager; | |
import javax.net.ssl.TrustManagerFactory; | |
import javax.net.ssl.X509TrustManager; | |
/** | |
* Represents an ordered list of {@link X509TrustManager}s with additive trust. If any one of the composed managers | |
* trusts a certificate chain, then it is trusted by the composite manager. | |
* | |
* This is necessary because of the fine-print on {@link SSLContext#init}: Only the first instance of a particular key | |
* and/or trust manager implementation type in the array is used. (For example, only the first | |
* javax.net.ssl.X509KeyManager in the array will be used.) | |
* | |
* @author codyaray | |
* @since 4/22/2013 | |
* @see <a href="http://stackoverflow.com/questions/1793979/registering-multiple-keystores-in-jvm"> | |
* http://stackoverflow.com/questions/1793979/registering-multiple-keystores-in-jvm | |
* </a> | |
*/ | |
@SuppressWarnings("unused") | |
public class CompositeX509TrustManager implements X509TrustManager { | |
private final List<X509TrustManager> trustManagers; | |
public CompositeX509TrustManager(List<X509TrustManager> trustManagers) { | |
this.trustManagers = ImmutableList.copyOf(trustManagers); | |
} | |
public CompositeX509TrustManager(KeyStore keystore) { | |
this.trustManagers = ImmutableList.of(getDefaultTrustManager(), getTrustManager(keystore)); | |
} | |
@Override | |
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { | |
for (X509TrustManager trustManager : trustManagers) { | |
try { | |
trustManager.checkClientTrusted(chain, authType); | |
return; // someone trusts them. success! | |
} catch (CertificateException e) { | |
// maybe someone else will trust them | |
} | |
} | |
throw new CertificateException("None of the TrustManagers trust this certificate chain"); | |
} | |
@Override | |
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { | |
for (X509TrustManager trustManager : trustManagers) { | |
try { | |
trustManager.checkServerTrusted(chain, authType); | |
return; // someone trusts them. success! | |
} catch (CertificateException e) { | |
// maybe someone else will trust them | |
} | |
} | |
throw new CertificateException("None of the TrustManagers trust this certificate chain"); | |
} | |
@Override | |
public X509Certificate[] getAcceptedIssuers() { | |
ImmutableList.Builder<X509Certificate> certificates = ImmutableList.builder(); | |
for (X509TrustManager trustManager : trustManagers) { | |
for (X509Certificate cert : trustManager.getAcceptedIssuers()) { | |
certificates.add(cert); | |
} | |
} | |
return Iterables.toArray(certificates.build(), X509Certificate.class); | |
} | |
public static TrustManager[] getTrustManagers(KeyStore keyStore) { | |
return new TrustManager[] { new CompositeX509TrustManager(keyStore) }; | |
} | |
public static X509TrustManager getDefaultTrustManager() { | |
return getTrustManager(null); | |
} | |
public static X509TrustManager getTrustManager(KeyStore keystore) { | |
return getTrustManager(TrustManagerFactory.getDefaultAlgorithm(), keystore); | |
} | |
public static X509TrustManager getTrustManager(String algorithm, KeyStore keystore) { | |
TrustManagerFactory factory; | |
try { | |
factory = TrustManagerFactory.getInstance(algorithm); | |
factory.init(keystore); | |
return Iterables.getFirst(Iterables.filter( | |
Arrays.asList(factory.getTrustManagers()), X509TrustManager.class), null); | |
} catch (NoSuchAlgorithmException | KeyStoreException e) { | |
e.printStackTrace(); | |
} | |
return null; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
try { | |
KeyStore keystore; // Get your own keystore here | |
SSLContext sslContext = SSLContext.getInstance("TLS"); | |
TrustManager[] tm = CompositeX509TrustManager.getTrustManagers(keystore); | |
sslContext.init(null, tm, null); | |
} catch (NoSuchAlgorithmException | KeyManagementException e) { | |
e.printStackTrace(); | |
} |
Hey, Thank you but in your old approach it worked
…On Wed, May 12, 2021 at 7:51 PM Hakky54 ***@***.***> wrote:
***@***.**** commented on this gist.
------------------------------
I think the solution is pretty straight forward. The CompositeTrustManager
is using an immutable list, but if you change that to an arraylist you will
be able to adjust it during runtime.
So if you add the following snippet it should probably do the trick:
public void addTrustStore(KeyStore trustStore) {
X509TrustManager trustManager = getTrustManager(trustStore);
this.trustManagers.add(trustManager);
}
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<https://gist.github.com/6eac419b18c6001aeadb#gistcomment-3740230>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AQOMNRINKIJA7XLE6WOSAQTTNKFH3ANCNFSM4JP6OBLQ>
.
java.lang.IllegalStateException: Unable to extract the trust manager on AndroidPlatform, sslSocketFactory is class com.google.android.gms.org.conscrypt.OpenSSLSocketFactoryImpl
at okhttp3.OkHttpClient$Builder.sslSocketFactory(OkHttpClient.kt:751)
Thank you so much. This solved my problem!!!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I think the solution is pretty straight forward. The CompositeTrustManager is using an immutable list, but if you change that to an arraylist you will be able to adjust it during runtime.
So if you add the following snippet it should probably do the trick: