41

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?

4
  • 1
    JDK version? HttpClient version? Also, if you could provide the full stack trace and the URL (is it a public website or not, are you using a self-signed certificate or not), it might help. Commented Feb 22, 2010 at 7:30
  • It's a self signed cert. I linked to the version of HttpClient I'm using (4.x, whatever's stable), and I'm using Java 6. I need to ignore this error and perform the get REGARDLESS of the site I'm connecting to. Commented Feb 22, 2010 at 14:48
  • 1
    Readers might be interested in this related question: Self Signed SSL acceptance Android Commented Mar 9, 2013 at 15:50
  • Note that it would be best to create a specific KeyStore or a TrustManager to connect to a specific server that is not verified by one of the pre-installed root certificates, or to create self signed certificates and use those. If you just skip over the problem, then your SSL connection is not secure anymore. Commented Oct 16, 2014 at 21:28

7 Answers 7

17

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; } } 
Sign up to request clarification or add additional context in comments.

5 Comments

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.
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.
Thanks for the edit, it never hurts to make that kind of security warning explicit.
@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?
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...
17

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 

1 Comment

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.
13

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.

3 Comments

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.
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.
This doesn't fix the problem, and the link leads to a parked page :/
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

Comments

0

Method returning a "secureClient" (in a Java 7 environnement - NetBeans IDE and GlassFish Server: port https by default 3920 ), hope this could help :

public DefaultHttpClient secureClient() { DefaultHttpClient httpclient = new DefaultHttpClient(); SSLSocketFactory sf; KeyStore trustStore; FileInputStream trustStream = null; File truststoreFile; // java.security.cert.PKIXParameters for the trustStore PKIXParameters pkixParamsTrust; KeyStore keyStore; FileInputStream keyStream = null; File keystoreFile; // java.security.cert.PKIXParameters for the keyStore PKIXParameters pkixParamsKey; try { trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); truststoreFile = new File(TRUSTSTORE_FILE); keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keystoreFile = new File(KEYSTORE_FILE); try { trustStream = new FileInputStream(truststoreFile); keyStream = new FileInputStream(keystoreFile); } catch (FileNotFoundException ex) { Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex); } try { trustStore.load(trustStream, PASSWORD.toCharArray()); keyStore.load(keyStream, PASSWORD.toCharArray()); } catch (IOException ex) { Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex); } catch (CertificateException ex) { Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex); } try { pkixParamsTrust = new PKIXParameters(trustStore); // accepts Server certificate generated with keytool and (auto) signed by SUN pkixParamsTrust.setPolicyQualifiersRejected(false); } catch (InvalidAlgorithmParameterException ex) { Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex); } try { pkixParamsKey = new PKIXParameters(keyStore); // accepts Client certificate generated with keytool and (auto) signed by SUN pkixParamsKey.setPolicyQualifiersRejected(false); } catch (InvalidAlgorithmParameterException ex) { Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex); } try { sf = new SSLSocketFactory(trustStore); ClientConnectionManager manager = httpclient.getConnectionManager(); manager.getSchemeRegistry().register(new Scheme("https", 3920, sf)); } catch (KeyManagementException ex) { Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex); } catch (UnrecoverableKeyException ex) { Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex); } } catch (NoSuchAlgorithmException ex) { Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex); } catch (KeyStoreException ex) { Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex); } // use the httpclient for any httpRequest return httpclient; } 

Comments

0

Your local JVM or remote server may not have the required ciphers. go here

https://www.oracle.com/java/technologies/javase-jce8-downloads.html

and download the zip file that contains: US_export_policy.jar and local_policy.jar

replace the existing files (you need to find the existing path in your JVM).

on a Mac, my path was here. /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/security

this worked for me.

Comments

0

I had SSLPeerUnverifiedException with org.apache.httpcomponents.httpasyncclient v4.1.5. When I just replace it with org.apache.httpcomponents.httpclient5 v5.5 exception changes to SSLHandshakeException. And solution for that: Migrating apache http client 5 from 5.3 to 5.4 trust all hosts and certificates deprecation replacement

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.