Reputation: 32117
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?
Upvotes: 13
Views: 1394
Reputation: 32117
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.
Upvotes: 2