Check In The Onreceivedsslerror() Method Of A Webviewclient If A Certificate Is Signed From A Specific Self-signed Ca
Solution 1:
I think you can try as the following:
@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
WebViewwebView= (WebView) findViewById(R.id.webView);
if (webView != null) {
// Get cert from raw resource...CertificateFactorycf= CertificateFactory.getInstance("X.509");
InputStreamcaInput= getResources().openRawResource(R.raw.rootca); // stored at \app\src\main\res\rawfinalCertificatecertificate= cf.generateCertificate(caInput);
caInput.close();
Stringurl="https://www.yourserver.com";
webView.setWebViewClient(newWebViewClient() {
@OverridepublicvoidonReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
// Get cert from SslErrorSslCertificatesslCertificate= error.getCertificate();
Certificatecert= getX509Certificate(sslCertificate);
if (cert != null && certificate != null){
try {
// Reference: https://developer.android.com/reference/java/security/cert/Certificate.html#verify(java.security.PublicKey)
cert.verify(certificate.getPublicKey()); // Verify here...
handler.proceed();
} catch (CertificateException | NoSuchAlgorithmException | InvalidKeyException | NoSuchProviderException | SignatureException e) {
super.onReceivedSslError(view, handler, error);
e.printStackTrace();
}
} else {
super.onReceivedSslError(view, handler, error);
}
}
});
webView.loadUrl(url);
}
} catch (Exception e){
e.printStackTrace();
}
}
// credits to @Heath Borders at http://stackoverflow.com/questions/20228800/how-do-i-validate-an-android-net-http-sslcertificate-with-an-x509trustmanagerprivate Certificate getX509Certificate(SslCertificate sslCertificate){
Bundlebundle= SslCertificate.saveState(sslCertificate);
byte[] bytes = bundle.getByteArray("x509-certificate");
if (bytes == null) {
returnnull;
} else {
try {
CertificateFactorycertFactory= CertificateFactory.getInstance("X.509");
return certFactory.generateCertificate(newByteArrayInputStream(bytes));
} catch (CertificateException e) {
returnnull;
}
}
}
If failed validation, logcat will have some information such as java.security.SignatureException: Signature was not verified...
If success, here's a screenshot:
Solution 2:
I think this should work (SSL_IDMISMATCH
means "Hostname mismatch").
@OverridepublicvoidonReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
SslCertificateserverCertificate= error.getCertificate();
if (error.hasError(SSL_UNTRUSTED)) {
// Check if Cert-Domain equals the Uri-DomainStringcertDomain= serverCertificate.getIssuedTo().getCName();
if(certDomain.equals(newURL(error.getUrl()).getHost())) {
handler.proceed();
}
}
else {
super.onReceivedSslError(view, handler, error);
}
}
If "hasError()" is not working, try error.getPrimaryError() == SSL_IDMISMATCH
Check Documentation of SslError for all error-types.
EDIT: I tested the function on my own self-cert server (its a Xampp), and I got Error #3.
That means you have to check for error.hasError(SslError.SSL_UNTRUSTED)
for a self-signed cert.
Solution 3:
based on documentation:
Have you tried using the method getIssuedBy().getDName()
of class SslCertificate. This method returns a String representing "The entity that issued this certificate".
Take a look here: http://developer.android.com/reference/android/net/http/SslCertificate.html#getIssuedBy()
Then you just need to know wich string is returned when it is self signed.
EDIT: I think that if it is selfsigned, that should return empty string, and if not, it would return the entity
Regards
Post a Comment for "Check In The Onreceivedsslerror() Method Of A Webviewclient If A Certificate Is Signed From A Specific Self-signed Ca"