Android - Validating Self-signed Certificates In Addition To Normal Ssl Certificates
Solution 1:
You haven't posted any code, so I can't be sure what you actually did. However, I'll assume that you're setting up a SSLContext
using only your custom X509TrustManager
subclass. That's fine, but what you can do is have your custom trust manager implementation also chain to the built-in trust managers. You can do this while setting up your trust manager; something like this should work:
private List<X509TrustManager> trustManagers = new ArrayList<X509TrustManager>();
publicMyCustomTrustManager() {
TrustManagerFactory tmFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmFactory.init((KeyStore)null);
for (TrustManager tm : tmFactory.getTrustManagers()) {
if (tm instanceof X509TrustManager)
trustManagers.add((X509TrustManager)tm);
}
}
So now your custom trust manager has a list of all the built-in trust managers. In your override of checkServerTrusted()
, you'll want to loop through the built-in trust managers and check each one by calling checkServerTrusted()
on each one in turn. If none of them trust the certificate, you can apply your own cert checking. If that passes, you can return normally. If not, just throw a CertificateException
as you'd otherwise do.
EDIT: Adding the below about doing things like host name verification.
You can also verify that the hostname in the certificate matches what you expect it to be. You'll want to pass in the valid hostname in your constructor for your custom trust manager and stash it in the class. Your checkServerTrusted()
method will get passed an array of X509Certificate
. Many "chains" will consist of just a single cert, but others will have several, depending on how the cA signed your cert. Either way, the first cert in the array should be "your" cert that you want to compare against.
After you check for basic cert validity using the trust managers, you'll then want to do something like this:
PrincipalsubjectDN= chain[0].getSubjectDN();
StringsubjectCN= parseDN(subjectDN.getName(), "CN");
if (this.allowedCN.equals(subjectCN)) {
// certificate is good
}
The implementation of parseDN()
is left up to you. subjectDN.getName()
will return a comma-separated list of key-value pairs (separated by =
), something like C=US,ST=California,L=Mountain View,O=Google Inc,CN=www.google.com
. You want the CN ("Common Name") value for your hostname comparison. Note that if you have a wildcard cert, it'll be listed as something like *.example.com
, so you'll need to do more than a simple equals match in that case.
Post a Comment for "Android - Validating Self-signed Certificates In Addition To Normal Ssl Certificates"