HttpGet with HTTPS : SSLPeerUnverifiedException

128,115

Solution 1

Using HttpClient 3.x, you need to do this:

Protocol easyHttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
Protocol.registerProtocol("https", easyHttps);

An implementation of EasySSLProtocolSocketFactory can be found here.

Solution 2

Note: Do not do this in production code, use http instead, or the actual self signed public key as suggested above.

On HttpClient 4.xx:

import static org.junit.Assert.assertEquals;

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;

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

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.junit.Test;

public class HttpClientTrustingAllCertsTest {

    @Test
    public void shouldAcceptUnsafeCerts() throws Exception {
        DefaultHttpClient httpclient = httpClientTrustingAllSSLCerts();
        HttpGet httpGet = new HttpGet("https://host_with_self_signed_cert");
        HttpResponse response = httpclient.execute( httpGet );
        assertEquals("HTTP/1.1 200 OK", response.getStatusLine().toString());
    }

    private DefaultHttpClient httpClientTrustingAllSSLCerts() throws NoSuchAlgorithmException, KeyManagementException {
        DefaultHttpClient httpclient = new DefaultHttpClient();

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, getTrustingManager(), new java.security.SecureRandom());

        SSLSocketFactory socketFactory = new SSLSocketFactory(sc);
        Scheme sch = new Scheme("https", 443, socketFactory);
        httpclient.getConnectionManager().getSchemeRegistry().register(sch);
        return httpclient;
    }

    private TrustManager[] getTrustingManager() {
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }

            @Override
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
                // Do nothing
            }

            @Override
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
                // Do nothing
            }

        } };
        return trustAllCerts;
    }
}

Solution 3

This answer follows on to owlstead and Mat's responses. It applies to SE/EE installations, not ME/mobile/Android SSL.

Since no one has yet mentioned it, I'll mention the "production way" to fix this: Follow the steps from the AuthSSLProtocolSocketFactory class in HttpClient to update your trust store & key stores.

  1. Import a trusted certificate and generate a truststore file

keytool -import -alias "my server cert" -file server.crt -keystore my.truststore

  1. Generate a new key (use the same password as the truststore)

keytool -genkey -v -alias "my client key" -validity 365 -keystore my.keystore

  1. Issue a certificate signing request (CSR)

keytool -certreq -alias "my client key" -file mycertreq.csr -keystore my.keystore

  1. (self-sign or get your cert signed)

  2. Import the trusted CA root certificate

keytool -import -alias "my trusted ca" -file caroot.crt -keystore my.keystore

  1. Import the PKCS#7 file containg the complete certificate chain

keytool -import -alias "my client key" -file mycert.p7 -keystore my.keystore

  1. Verify the resultant keystore file's contents

keytool -list -v -keystore my.keystore

If you don't have a server certificate, generate one in JKS format, then export it as a CRT file. Source: keytool documentation

keytool -genkey -alias server-alias -keyalg RSA -keypass changeit
    -storepass changeit -keystore my.keystore

keytool -export -alias server-alias -storepass changeit
    -file server.crt -keystore my.keystore

Solution 4

This exception will come in case your server is based on JDK 7 and your client is on JDK 6 and using SSL certificates. In JDK 7 sslv2hello message handshaking is disabled by default while in JDK 6 sslv2hello message handshaking is enabled. For this reason when your client trying to connect server then a sslv2hello message will be sent towards server and due to sslv2hello message disable you will get this exception. To solve this either you have to move your client to JDK 7 or you have to use 6u91 version of JDK. But to get this version of JDK you have to get the

Share:
128,115
Stefan Kendall
Author by

Stefan Kendall

Updated on August 02, 2022

Comments

  • Stefan Kendall
    Stefan Kendall almost 2 years

    Using HttpClient, I receive the following error when attempting to communicate over HTTPS:

    Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated.

    Here is my code:

    URI loginUri = new URI("https://myUrl.asp");
    
    HttpClient httpclient = new DefaultHttpClient();
    HttpGet httpget = new HttpGet( loginUri );
    HttpResponse response = httpclient.execute( httpget );
    

    How do I suppress or remove this error?

  • Stefan Kendall
    Stefan Kendall almost 13 years
    Updated URL. All you really need to do is google EasySSLProtocolSocketFactory. The exact string is so specific that it seemed like there were no bad results.
  • Bruno
    Bruno about 12 years
    It should be noted that this method does exactly what the question asks for: it supresses the error message. It doesn't actually solve the problem since the connection is insecure. The right way would be to import the remote certificate explictly in your trust store.
  • Maarten Bodewes
    Maarten Bodewes over 11 years
    And again, for anybody that is interested in security, this does not fix the underlying problem. Import the certificate in your certificate store, but don't trust all connections as you might as well not use SSL.
  • Jonas Andersson
    Jonas Andersson over 11 years
    Of course. Doing the above in production code would be incredibly counter productive. But if you don't care about security, for example in an end-to-end test against a development server, it's nice to not depend on the server certs.
  • Maarten Bodewes
    Maarten Bodewes over 11 years
    Thanks for the edit, it never hurts to make that kind of security warning explicit.
  • dalvarezmartinez1
    dalvarezmartinez1 over 10 years
    @owlstead "you might as well not use SSL" I use SSL only for encryption, not for authenticating the server to the client, how is this not safe?
  • Jonas Andersson
    Jonas Andersson over 10 years
    I assume your purpose for using encryption is preventing man-in-the-middle to read your data. If so, without authenticating the cert, you don't know who is at the other end, it could be the man-in-the-middle proxying the communication, i.e. decrypting it, reading it, encrypting it, passing it on. You'll never know...
  • daiscog
    daiscog over 9 years
    It's worth noting that steps 2-7 are only required if you need to implement client authentication, too (i.e., letting the server authenticate the client). In most cases, step 1 alone will be enough.
  • cheftao
    cheftao over 8 years
    how do i create the server.crt?
  • Barett
    Barett over 8 years
    Edited to include server.crt creation steps.
  • Steven Schlansker
    Steven Schlansker almost 6 years
    This doesn't fix the problem, and the link leads to a parked page :/