Home » Enterprise Java » Security » How to Fix : java.security.cert.CertificateException: No name matching localhost found

How to Fix the exception ” java.security.cert.CertificateException: No name matching localhost found”, when client uses URL with “localhost” as host name to access some secure service over HTTPS? In this article we will check the root cause of the issue and will try two different solutions two fix the same.

When Do You Encounter the Error : java.security.cert.CertificateException: No name matching localhost found?

When you use self signed certificate for services such as secure web service and try to access the service over HTTPS from a client using “localhost”, you may encounter the error “java.security.cert.CertificateException: No name matching localhost found”.
The error can also be something like “java.security.cert.CertificateException: No name matching <hostname> found”, where, the “hostname” can be anything.

…..
Caused by: javax.net.ssl.SSLHandshakeException: 
    java.security.cert.CertificateException: No name matching localhost found
	at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1611)
	at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:187)
	at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:181)
	......
Caused by: java.security.cert.CertificateException: No name matching localhost found
	at sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:210)
	at sun.security.util.HostnameChecker.match(HostnameChecker.java:77)
…….

Root Cause of the Exception: java.security.cert.CertificateException: No name matching <host> found

At run-time, Java check host name against the names specified in a digital certificate as required for TLS and LDAP.
So if you are using for example, https://localhost:8443/MyService/.. , the runtime will check if the certificate allows use of the given DNS name, in this case “localhost”. This matching is performed using the matching rules specified by RFC2459.

As per the java doc, “If a subjectAltName extension of type dNSName is present, that MUST be used as the identity. Otherwise, the (most specific) Common Name field in the Subject field of the certificate MUST be used. Although the use of the Common Name is existing practice, it is deprecated and Certification Authorities are encouraged to use the dNSName instead.
Also “If more than one identity of a given type is present in the certificate (e.g., more than one dNSName name, a match in any one of the set is considered acceptable.)

The above points indicate that, the certificate CN (Common Name) should be the same as host name in the URL. If the CN in the certificate is not the same as the host name, you will get the error “java.security.cert.CertificateException: No name matching <the_host_name_used> found”, where , “the_host_name_used” is the host name you used as part of the URL in your client application.

How to solve the error “java.security.cert.CertificateException: No name matching localhost found”?

Method 1: Change the Certificate CN name

The first step is to verify the CN (Common Name) in the certificate. Please not that, you cannot change the CN in an already created certificate. This is because, a certificate is designed specifically so that this data can’t be modified after its creation. It is part of the certificate.

<X509IssuerName>CN=localhost, OU=home, O=home, L=city,ST=state, C=in</X509IssuerName>

So you need to create a new certificate with the hostname as “localhost” or any other hostname you want to use. Example is given below. You can use the java keytool tool to create your self-signed certificate with the “localhost” CN.

F:\myservice\src>keytool -genkey -alias serverkey -keypass nosecret -keyalg RSA -sigalg SHA1withRSA -keystore server.keystore -storepass nostoresecret
What is your first and last name?
  [Unknown]:  localhost
What is the name of your organizational unit?
  [Unknown]:  globinch ws
What is the name of your organization?
  [Unknown]:  globinch
What is the name of your City or Locality?
  [Unknown]:  Bangalore
What is the name of your State or Province?
  [Unknown]:  KAR
What is the two-letter country code for this unit?
  [Unknown]:  IN
Is CN=localhost, OU=globinch ws, O=globinch, L=Bangalore, ST=KAR, C=IN correct?
  [no]:  yes

That’s all. You need to apply this certificate and setup the web server. Now if you use endpoint such as https://localhost:8443/MyService/..” ,the java security run-time will accept it.

Implement the verify() method of HostnameVerifier

HostnameVerifier is the base interface for hostname verification. As per java doc “During handshaking, if the URL’s hostname and the server’s identification hostname mismatch, the verification mechanism can call back to implementers of this interface to determine if this connection should be allowed”.
These callbacks are used when the default rules for URL hostname verification fail.
The HttpsURLConnection class uses HostnameVerifier and SSLSocketFactory. You can set the HostnameVerifier using the setDefaultHostnameVerifier(setDefaultHostnameVerifier) method. See example below.

javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
    new javax.net.ssl.HostnameVerifier(){
 
        public boolean verify(String hostname,
                javax.net.ssl.SSLSession sslSession) {
            if (hostname.equals("localhost")) {
                return true;
            }
            return false;
        }
    });

So during handshaking, if the URL’s hostname and the server’s identification hostname mismatch, it will invoke the above verify implementation. The above code returns “true” for hostname localhost”, and the connection is allowed.

References:

email
x
Get Enterprise Java Newsletter

Enter your email and stay on top of things,