Trust all certificates with HttpClient over HTTPS


Harrison Leigh:

Recently posted a question about over HttpClientHttps ( found here ). I've made some progress, but I'm running into a new problem. As with my last question, I can't seem to find an example that works for me. Basically, I want my client to accept any certificate (since I'm only pointing to one server), but I keep gettingjavax.net.ssl.SSLException: Not trusted server certificate exception.

This is what I have:


    public void connect() throws A_WHOLE_BUNCH_OF_EXCEPTIONS {

        HttpPost post = new HttpPost(new URI(PROD_URL));
        post.setEntity(new StringEntity(BODY));

        KeyStore trusted = KeyStore.getInstance("BKS");
        trusted.load(null, "".toCharArray());
        SSLSocketFactory sslf = new SSLSocketFactory(trusted);
        sslf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        SchemeRegistry schemeRegistry = new SchemeRegistry();
        schemeRegistry.register(new Scheme ("https", sslf, 443));
        SingleClientConnManager cm = new SingleClientConnManager(post.getParams(),
                schemeRegistry);

        HttpClient client = new DefaultHttpClient(cm, post.getParams());
        HttpResponse result = client.execute(post);
    }

This is the error I get:

    W/System.err(  901): javax.net.ssl.SSLException: Not trusted server certificate 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:360) 
    W/System.err(  901):    at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:92) 
    W/System.err(  901):    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:321) 
    W/System.err(  901):    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:129) 
    W/System.err(  901):    at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164) 
    W/System.err(  901):    at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) 
    W/System.err(  901):    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:348) 
    W/System.err(  901):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) 
    W/System.err(  901):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487) 
    W/System.err(  901):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465) 
    W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity.connect(MainActivity.java:129) 
    W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity.access$0(MainActivity.java:77) 
    W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity$2.run(MainActivity.java:49) 
    W/System.err(  901): Caused by: java.security.cert.CertificateException: java.security.InvalidAlgorithmParameterException: the trust anchors set is empty 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:157) 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:355) 
    W/System.err(  901):    ... 12 more 
    W/System.err(  901): Caused by: java.security.InvalidAlgorithmParameterException: the trust anchors set is empty 
    W/System.err(  901):    at java.security.cert.PKIXParameters.checkTrustAnchors(PKIXParameters.java:645) 
    W/System.err(  901):    at java.security.cert.PKIXParameters.<init>(PKIXParameters.java:89) 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.<init>(TrustManagerImpl.java:89) 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.TrustManagerFactoryImpl.engineGetTrustManagers(TrustManagerFactoryImpl.java:134) 
    W/System.err(  901):    at javax.net.ssl.TrustManagerFactory.getTrustManagers(TrustManagerFactory.java:226)W/System.err(  901):     at org.apache.http.conn.ssl.SSLSocketFactory.createTrustManagers(SSLSocketFactory.java:263) 
    W/System.err(  901):    at org.apache.http.conn.ssl.SSLSocketFactory.<init>(SSLSocketFactory.java:190) 
    W/System.err(  901):    at org.apache.http.conn.ssl.SSLSocketFactory.<init>(SSLSocketFactory.java:216) 
    W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity.connect(MainActivity.java:107) 
    W/System.err(  901):    ... 2 more
Daniel:

Note: Do not implement this functionality in production code used on networks that you do not fully trust. Especially anything over the public internet.

Your question is what I want to know. After some searching, the conclusion is as follows.

In the HttpClient way, you should create a custom class from org.apache.http.conn.ssl.SSLSocketFactory, not an org.apache.http.conn.ssl.SSLSocketFactory itself. Some clues can be found in this article. Custom SSL handling has stopped working on Android 2.2 FroYo .

An example would be like...

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.conn.ssl.SSLSocketFactory;
public class MySSLSocketFactory extends SSLSocketFactory {
    SSLContext sslContext = SSLContext.getInstance("TLS");

    public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
        super(truststore);

        TrustManager tm = new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };

        sslContext.init(null, new TrustManager[] { tm }, null);
    }

    @Override
    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
        return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
    }

    @Override
    public Socket createSocket() throws IOException {
        return sslContext.getSocketFactory().createSocket();
    }
}

and use this class when creating an instance of HttpClient.

public HttpClient getNewHttpClient() {
    try {
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        trustStore.load(null, null);

        MySSLSocketFactory sf = new MySSLSocketFactory(trustStore);
        sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        HttpParams params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        registry.register(new Scheme("https", sf, 443));

        ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

        return new DefaultHttpClient(ccm, params);
    } catch (Exception e) {
        return new DefaultHttpClient();
    }
}

By the way, the link below is for those who are looking for a solution for HttpURLConnection. Https connection Android

I've tested both of the above solutions on froyo and in my case they both worked like a charm. Finally, using HttpURLConnection may have problems with redirects, but that's off topic.

Note: Before deciding to trust all certificates, you should probably understand the site well and not be a hazard to end users.

Indeed, you should carefully consider the risks you take, including the impact of hacking simulation sites mentioned in the comments below which I greatly appreciate. While it may be difficult to deal with all certificates in some cases, you'd better be aware of the implicit downsides of trusting all certificates.

Related


Trust all certificates with HttpClient over HTTPS

Harrison Leigh: Recently posted a question about over HttpClientHttps ( found here ). I've made some progress, but I'm running into a new problem. As with my last question, I can't seem to find an example that works for me. Basically, I want my client to accep

Trust all certificates with HttpClient over HTTPS

Harrison Leigh: Recently posted a question about over HttpClientHttps ( found here ). I've made some progress, but I'm running into a new problem. As with my last question, I can't seem to find an example that works for me. Basically, I want my client to accep

Trust all certificates with okHttp

seato: seato: For testing, I'm trying to add a socket factory to my okHttp client that trusts everything when setting up the proxy. This has been done many times, but my implementation of the trusted socket factory seems to be missing something: class TrustEve

Trust all certificates with okHttp

seato: seato: For testing, I'm trying to add a socket factory to my okHttp client that trusts everything when setting up the proxy. This has been done many times, but my implementation of the trusted socket factory seems to be missing something: class TrustEve

Trust all certificates with okHttp

seato: seato: For testing, I'm trying to add a socket factory to my okHttp client that trusts everything when setting up the proxy. This has been done many times, but my implementation of the trusted socket factory seems to be missing something: class TrustEve

Make Java accept all certificates over HTTPS

sketch: I'm trying to get Java to accept all certificates over HTTPS. This is for testing purposes. No errors were found until the certificate was obtained. However, after adding the following code before my code, I get an HTTPS hostname wrong: should be <sub.

Make Java accept all certificates over HTTPS

sketch: I'm trying to get Java to accept all certificates over HTTPS. This is for testing purposes. No errors were found until the certificate was obtained. However, after adding the following code before my code, I get an HTTPS hostname wrong: should be <sub.

Make Java accept all certificates over HTTPS

sketch: I'm trying to get Java to accept all certificates over HTTPS. This is for testing purposes. No errors were found until the certificate was obtained. However, after adding the following code before my code, I get an HTTPS hostname wrong: should be <sub.

Use Httpclient to trust self-signed certificates

wood more wood I'm trying to make a web request that fails due to a self-signed certificate: Client = new HttpClient(); HttpResponseMessage Response = await Client.GetAsync(Uri)//defined elsewhere This will throw a trust failure exception. I tried allowing

Use Httpclient to trust self-signed certificates

wood more wood I'm trying to make a web request that fails due to a self-signed certificate: Client = new HttpClient(); HttpResponseMessage Response = await Client.GetAsync(Uri)//defined elsewhere This will throw a trust failure exception. I tried allowing

Use Httpclient to trust self-signed certificates

wood more wood I'm trying to make a web request that fails due to a self-signed certificate: Client = new HttpClient(); HttpResponseMessage Response = await Client.GetAsync(Uri)//defined elsewhere This will throw a trust failure exception. I tried allowing

Trust all SSL certificates in Java Playframework 2.2

asvignesh: I'm trying to call a web service (with a self-signed SSL certificate) in the Play framework using the following function: public static play.libs.F.Promise<Result> webcall() { String feedUrl = "https://10.0.1.1/client/api"; final play.

CXF RESTful client - how to trust all certificates?

sdoca: I wrote a Jersey RESTful client that uses the Dumb X509TrustManager and HostnameVerifier to trust all SSL certificates on our lab system to make it easier to handle self-signed certificates. ClientConfig config = new DefaultClientConfig();

CXF RESTful client - how to trust all certificates?

sdoca: I wrote a Jersey RESTful client that uses the Dumb X509TrustManager and HostnameVerifier to trust all SSL certificates on our lab system to make it easier to handle self-signed certificates. ClientConfig config = new DefaultClientConfig();

Trust all SSL certificates in Java Playframework 2.2

asvignesh: I'm trying to call a web service (with a self-signed SSL certificate) in the Play framework using the following function: public static play.libs.F.Promise<Result> webcall() { String feedUrl = "https://10.0.1.1/client/api"; final play.

Trust all SSL certificates in Java Playframework 2.2

Avines I'm trying to call a web service (with a self-signed SSL certificate) in the Play framework using the following function: public static play.libs.F.Promise<Result> webcall() { String feedUrl = "https://10.0.1.1/client/api"; final play.libs

Trust all SSL certificates in Java Playframework 2.2

asvignesh: I'm trying to call a web service (with a self-signed SSL certificate) in the Play framework using the following function: public static play.libs.F.Promise<Result> webcall() { String feedUrl = "https://10.0.1.1/client/api"; final play.

JAX-WS, trust all ssl certificates doesn't work

Clemens Yes, I know, I shouldn't trust all SSL certificates. However, since there is a VPN tunnel, and depending on the transition phase, different servers (with different SSL certificates) need to be requested, I prefer the ignore-server-ssl-certificate(s) ap

Lynx thinks my profile doesn't trust all certificates

max purifier I try to access what I think is a valid ssl authentication page https://google.com , but lynx always saysSSL error:The certificate is NOT trusted. The certificate is...-Continue? (n) I have not done any configuration of lynx except the following c

Lynx thinks my profile doesn't trust all certificates

max purifier I try to access what I think is a valid ssl authentication page https://google.com , but lynx always saysSSL error:The certificate is NOT trusted. The certificate is...-Continue? (n) I have not done any configuration of lynx except the following c