Android's WebViewClient
calls onReceivedSslError
when it encounters an untrusted cert. However, the SslError
object I receive in that call doesn't have any way public way to get to the underlying X509Certificate
to validate it against an existing TrustStoreManager
. Looking at the source, I can access the X509Certificate
's encoded bytes thusly:
public void onReceivedSslError(WebView view, SslErrorHandler handler,
SslError error) {
Bundle bundle = SslCertificate.saveState(error.getCertificate());
X509Certificate x509Certificate;
byte[] bytes = bundle.getByteArray("x509-certificate");
if (bytes == null) {
x509Certificate = null;
} else {
try {
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
Certificate cert = certFactory.generateCertificate(new ByteArrayInputStream(bytes));
x509Certificate = (X509Certificate) cert;
} catch (CertificateException e) {
x509Certificate = null;
}
}
// Now I have an X509Certificate I can pass to an X509TrustManager for validation.
}
Obviously, this is private API and is fragile, though I assume it is fairly reliable since they can't change the bundle format. Is there a better way?
User taps the validation link, and the app makes a request to the server. The certificate is fetched and tested to see if it is recognized by the Android OS already. If it isn’t a known certificate, the details of the certificate are presented for the user to look at.
When the application validates the trust chain for our custom certificate, it will find our custom CA in the trust store and our certificate will be trusted. If the application targets Android versions later than 6.0, however, it won’t trust the user-added CA store.
The simplest way to avoid SSL errors is to have a valid, trusted certificate. This is relatively easy if you can install new, trusted CAs to the device – if the operating system trusts your CA, it will trust a certificate signed by your CA.
The techniques below all share the common goal of convincing a mobile application to trust the certificate provided by our intercepting proxy. The simplest way to avoid SSL errors is to have a valid, trusted certificate.
After a long wait it seems that a method called getX509Certificate(): java.security.cert.X509Certificate
has been added to SslCertificate
after my feature request as issue 36984840.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With