9

I am trying to call a HTTPS REST API through Jersey Client. And on the course of development i stumble upon following error :

Exception in thread "main" com.sun.jersey.api.client.ClientHandlerException: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching mvn.signify.abc.com found at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:149) at com.sun.jersey.api.client.Client.handle(Client.java:648) at com.sun.jersey.api.client.WebResource.handle(WebResource.java:670) at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74) at com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:503) at com.lftechnology.sbworkbench.utility.utils.PingFederateUtility.main(PingFederateUtility.java:32) Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching mvn.signify.abc.com found 

So I googled it out for a bit and found tons of solution for it , which actually works.

  1. HTTPS using Jersey Client
  2. https://gist.github.com/outbounder/1069465
  3. How to fix the "java.security.cert.CertificateException: No subject alternative names present" error?
  4. http://www.mkyong.com/webservices/jax-ws/java-security-cert-certificateexception-no-name-matching-localhost-found/
  5. http://java.globinch.com/enterprise-java/security/fix-java-security-certificate-exception-no-matching-localhost-found/

They are in different domain but they have a common solution to work it out.

Scenario

I am currently using a self created self-signed certificate in development environment. And hence it is bound to show up the issue.

Question

The above mentioned solution focus on skipping / allowing all certificates to be verified.

But when i move it to the production environment , then i have access to Valid Signed Certificate from trustworthy source.

  1. So are these solution any help when I move to production?
  2. Is it OK to skip SSL verification ?
  3. What are the other alternate way to achieve a common solution for both development and production environment?

P.S

The solution i used was ,

try { // Create a trust manager that does not validate certificate chains TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] certs, String authType) { } public void checkServerTrusted(X509Certificate[] certs, String authType) { } } }; // Install the all-trusting trust manager SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); // Create all-trusting host name verifier HostnameVerifier allHostsValid = new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }; // Install the all-trusting host verifier HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (KeyManagementException e) { e.printStackTrace(); } 

which i then in-cooperate with Jersey to make it work. And it is working great.

So , the Question again. Is this solution viable to be used in Production environment? However, you don’t want to modify the returning entities, it’s much better to fetch the entities in read-only mode. This will allows Hibernate to discard the associated detached state which is used by the dirty checking mechanism to detect entity state modifications. More, read-only entities are skipped during flushing.

2
  • 3
    "Is it OK to skip SSL verification ?" - rather not.. or did you not here about Apples GOTO FAIL?! Commented Aug 1, 2014 at 12:06
  • 3
    "So , the Question again. Is this solution viable to be used in Production environment?" - not, its not. Its irresponsible and grossly negligent. Commented Aug 2, 2014 at 7:39

3 Answers 3

14

I am currently using a self created self-signed certificate in development environment. ... javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching dev.ppc.lftechnology.com found

It appears the self signed certificate is incorrect.

Below is the OpenSSL CONF file I use to create self signed certificates and certificate requests to use during testing. Save it as example-com.conf. Change the DNS names under [ alternate_names ] to suit your tastes. You can even put localhost, localhost.localdomain and 127.0.0.1 in there for testing.

If you want to create a self signed certificate, then use:

openssl req -config example-com.conf -new -x509 -newkey rsa:2048 \ -nodes -keyout example-com.key.pem -days 365 -out example-com.cert.pem 

If you want to create a signing request (CSR) that will be signed by a trusted authority, then use:

openssl req -config example-com.conf -new -newkey rsa:2048 \ -nodes -keyout example-com.key.pem -days 365 -out example-com.req.pem 

The difference between a self signed certificate and a signing request is the -x509 option. With -x509 present, a self signed certificate is created. The absence of -x509 means a request is created.

If you want to print your self signed certificate or request to see what's actually in it, then use:

openssl x509 -in example-com.cert.pem -text -noout openssl req -in example-com.req.pem -text -noout 

If you want to test the server, then use s_client:

openssl s_client -connect <server>:<port> -CAfile <trust-anchor.pem> 

The above command should finish with a message similar to Verify OK (0). If you don't receive Verify OK (0), then fix your test rig. Once OpenSSL completes successfully, then that becomes your baseline.


[ req ] default_bits = 2048 default_keyfile = server-key.pem distinguished_name = subject req_extensions = req_extensions x509_extensions = cert_extensions string_mask = utf8only [ subject ] countryName = Country Name (2 letter code) countryName_default = US stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = NY localityName = Locality Name (eg, city) localityName_default = New York organizationName = Organization Name (eg, company) organizationName_default = Example, LLC # Use a friendly name here. Its presented to the user. # The server's DNS name show up in Subject Alternate Names. Plus, # DNS names here is deprecated by both IETF and CA/Browser Forums. commonName = Common Name (e.g. server FQDN or YOUR name) commonName_default = Example Company emailAddress = Email Address emailAddress_default = [email protected] [ cert_extensions ] subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer basicConstraints = CA:FALSE keyUsage = digitalSignature, keyEncipherment # extendedKeyUsage = serverAuth subjectAltName = @alternate_names nsComment = "OpenSSL Generated Certificate" [ req_extensions ] subjectKeyIdentifier = hash basicConstraints = CA:FALSE keyUsage = digitalSignature, keyEncipherment # extendedKeyUsage = serverAuth subjectAltName = @alternate_names nsComment = "OpenSSL Generated Certificate" [ alternate_names ] DNS.1 = example.com DNS.2 = www.example.com DNS.3 = mail.example.com DNS.4 = ftp.example.com # Add these if you need them. But usually you don't want them or # need them in production. You may need them for development. # DNS.5 = localhost # DNS.6 = localhost.localdomain # DNS.7 = 127.0.0.1 

Is it OK to skip SSL verification ?

No. That's very irresponsible. If you are not going to use PKIX correctly, then why use it at all?

This comes to mind: The Most Dangerous Code in the World: Validating SSL Certificates in Non-Browser Software.


HostnameVerifier allHostsValid = new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }; 

Its better to load your self signed certificate in a Keystore (or load your private CA), and then pass it to SSLContext.init. Then everything works as intended, and there's no need to trust everything or return true from verify.

Bruno and EJP have plenty of answers covering that subject.


What are the other alternate way to achieve a common solution for both development and production environment?

Use a well formed certificate that chains back to a trusted root.

For testing, you can create a self signed certificate. Or, create a certificate request and have it signed by your internal CA in a private PKI. In this case, you need to trust your self signed certificate or trust your internal CA.

For production, you can use a certificate signed by one of the members of the CA Zoo so others outside the organization trusts it too. StartCom and CACert offer free Class 1 certificates.

Class 1 certificates are usually domain validated and don't allow wild cards. While the Class 1 is issued for free, they charge for revocation because that's where the cost lies.

If you need a wild card, then you will usually to purchase a Class 2 or higher.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks @jww it is an awesome answer. I have updated my question a little bit regarding the solution i mentioned.
Thanks for you valuable insight @jww.
hi @jww it is working fine for localhost {DNS}, When i am giving the local ip address like 192.168.1.56 it is not working.Please help me out
@Srinivasu - Add something similar to DNS.5 = 192.168.1.56. If its still not working, then its related to browsers. But I have not been able to track down what exactly browsers find offensive about IP addresses (versus DNS names). Ryan Sleevi of Google explained it at Comments on draft-ietf-websec-key-pinning, but I have not digested it yet.
@jww Browser is not giving any problem, Jersey is giving problem
6

@jww rightly answers the question

Is it OK to skip SSL verification? No. That's very irresponsible.

However, in some cases you may not control the server in question to be able to install a valid certificate. If the server belongs to someone else, and you trust that server, a better solution is to use a "white list" to validate certificates only for trusted servers, otherwise use normal validation.

public static class WhitelistHostnameVerifier implements HostnameVerifier { private static final HostnameVerifier defaultHostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier(); private Set<String> trustedHosts; public WhitelistHostnameVerifier(Set<String> trustedHosts) { this.trustedHosts = trustedHosts; } @Override public boolean verify(String hostname, SSLSession session) { if (trustedHosts.contains(hostname)) { return true; } else { return defaultHostnameVerifier.verify(hostname, session); } } } 

And install it once:

HttpsURLConnection.setDefaultHostnameVerifier( new WhitelistHostnameVerifier(Sets.newHashSet("trustedhost.mydomain.com"))); 

If you're going to disable a security check, don't do it globally...

Comments

1

There is a label software bug with the Java Keytool for Java version 1.7.0_60-b19, when creating a self signed certificate. See these instructions for a reference.

https://www.sslshopper.com/article-how-to-create-a-self-signed-certificate-using-java-keytool.html

When it prompts you for "What is your first and last name?", instead of typing your name, you should enter the common name, or (fully qualified domain name of your server).

[root@localhost ~]# keytool -genkey -keyalg RSA -alias myalias -keystore keystore.jks -storepass XXXXXX -validity 360 -keysize 2048 What is your first and last name? [Unknown]: Angus MacGyver What is the name of your organizational unit? [Unknown]: My Department What is the name of your organization? [Unknown]: My Company What is the name of your City or Locality? [Unknown]: My City What is the name of your State or Province? [Unknown]: My State What is the two-letter country code for this unit? [Unknown]: US Is CN=Angus MacGyver, OU=My Department, O=My Company, L=My City, ST=My State, C=US correct? [no]: yes Enter key password for <selfsigned> (RETURN if same as keystore password):XXXXXX Re-enter new password:XXXXXX 

You can verify if the "CN" (common name) attribute gets set correctly by calling this:

[root@localhost ~]# keytool -v -list -keystore keystore.jks 

Find Java version:

[root@localhost ~]# java -version java version "1.7.0_60" Java(TM) SE Runtime Environment (build 1.7.0_60-b19) Java HotSpot(TM) Client VM (build 24.60-b09, mixed mode, sharing) 

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.