Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix the "java.security.cert.CertificateException: No subject alternative names present" error?

People also ask

How do I fix No Subject Alternative DNS name matching?

Resolving The Problem In order to resolve the issue either: Regenerate the LDAP server certificate so that the certificate's subject alternate name or certificate's subject name matches the hostname of the LDAP server.

How do I add a Subject Alternative Name to a certificate?

To add a Subject Alternative NameSelect SSL Certificates and then select Manage for the certificate you want to change. Select Change Subject Alternative Names. For Add a domain, enter the SAN you want to add and then select Add.

What is Java security cert?

The Java Certificate class ( java. security. cert. Certificate ) represents a cryptographic identity certificate. A Java Certificate class instance contains name plus other details of the entity it identifies, plus possibly a digital signature from a Certificate Authority (CA).


I fixed the problem by disabling HTTPS checks using the approach presented here:

I put following code into the the ISomeService class:

static {
    disableSslVerification();
}

private static void disableSslVerification() {
    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();
    }
}

Since I'm using the https://AAA.BBB.CCC.DDD:9443/ISomeService for testing purposes only, it's a good enough solution, but do not do this in production.

Note that you can also disable SSL for "one connection at a time" ex:

 // don't call disableSslVerification but use its internal code:
 HttpURLConnection conn = (HttpURLConnection) url.openConnection();
 if (conn instanceof HttpsURLConnection) {
    HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
    httpsConn.setHostnameVerifier(allHostsValid);
    httpsConn.setSSLSocketFactory(sc.getSocketFactory());
 }

I've the same problem and solved with this code. I put this code before the first call to my webservices.

javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
  new javax.net.ssl.HostnameVerifier(){

      public boolean verify(String hostname,
             javax.net.ssl.SSLSession sslSession) {
          return hostname.equals("localhost"); // or return true
      }
  });

It's simple and works fine.

Here is the original source.


This is an old question, yet I had the same problem when moving from JDK 1.8.0_144 to jdk 1.8.0_191

We found a hint in the changelog:

Changelog

we added the following additional system property, which helped in our case to solve this issue:

-Dcom.sun.jndi.ldap.object.disableEndpointIdentification=true

The verification of the certificate identity is performed against what the client requests.

When your client uses https://xxx.xxx.xxx.xxx/something (where xxx.xxx.xxx.xxx is an IP address), the certificate identity is checked against this IP address (in theory, only using an IP SAN extension).

If your certificate has no IP SAN, but DNS SANs (or if no DNS SAN, a Common Name in the Subject DN), you can get this to work by making your client use a URL with that host name instead (or a host name for which the cert would be valid, if there are multiple possible values). For example, if you cert has a name for www.example.com, use https://www.example.com/something.

Of course, you'll need that host name to resolve to that IP address.

In addition, if there are any DNS SANs, the CN in the Subject DN will be ignored, so use a name that matches one of the DNS SANs in this case.


To import the cert:

  1. Extract the cert from the server, e.g. openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443 > certs.txt This will extract certs in PEM format.
  2. Convert the cert into DER format as this is what keytool expects, e.g. openssl x509 -in certs.txt -out certs.der -outform DER
  3. Now you want to import this cert into the system default 'cacert' file. Locate the system default 'cacerts' file for your Java installation. Take a look at How to obtain the location of cacerts of the default java installation?
  4. Import the certs into that cacerts file: sudo keytool -importcert -file certs.der -keystore <path-to-cacerts> Default cacerts password is 'changeit'.

If the cert is issued for an FQDN and you're trying to connect by IP address in your Java code, then this should probably be fixed in your code rather than messing with certificate itself. Change your code to connect by FQDN. If FQDN is not resolvable on your dev machine, simply add it to your hosts file, or configure your machine with DNS server that can resolve this FQDN.


I fixed this issue in a right way by adding the subject alt names in certificate rather than making any changes in code or disabling SSL unlike what other answers suggest here. If you see clearly the exception says the "Subject alt names are missing" so the right way should be to add them

Please look at this link to understand step by step.

The above error means that your JKS file is missing the required domain on which you are trying to access the application.You will need to Use Open SSL and the key tool to add multiple domains

  1. Copy the openssl.cnf into a current directory
  2. echo '[ subject_alt_name ]' >> openssl.cnf
  3. echo 'subjectAltName = DNS:example.mydomain1.com, DNS:example.mydomain2.com, DNS:example.mydomain3.com, DNS: localhost'>> openssl.cnf
  4. openssl req -x509 -nodes -newkey rsa:2048 -config openssl.cnf -extensions subject_alt_name -keyout private.key -out self-signed.pem -subj '/C=gb/ST=edinburgh/L=edinburgh/O=mygroup/OU=servicing/CN=www.example.com/[email protected]' -days 365
  5. Export the public key (.pem) file to PKS12 format. This will prompt you for password

    openssl pkcs12 -export -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -export -in
    self-signed.pem -inkey private.key -name myalias -out keystore.p12
    
  6. Create a.JKS from self-signed PEM (Keystore)

    keytool -importkeystore -destkeystore keystore.jks -deststoretype PKCS12 -srcstoretype PKCS12 -srckeystore keystore.p12
    
  7. Generate a Certificate from above Keystore or JKS file

    keytool -export -keystore keystore.jks -alias myalias -file selfsigned.crt
    
  8. Since the above certificate is Self Signed and is not validated by CA, it needs to be added in Truststore(Cacerts file in below location for MAC, for Windows, find out where your JDK is installed.)

    sudo keytool -importcert -file selfsigned.crt -alias myalias -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/security/cacerts
    

Original answer posted on this link here.


my problem with getting this error was resolved by using the full URL "qatest.ourCompany.com/webService" instead of just "qatest/webService". Reason was that our security certificate had a wildcard i.e. "*.ourCompany.com". Once I put in the full address the exception went away. Hope this helps.