Java CertificateException “No subject alternative names matching IP address … found”

前端 未结 6 1679
隐瞒了意图╮
隐瞒了意图╮ 2020-12-31 10:39

I\'m trying to implement a selfsigned certificate into my webserver, and it\'s working already with firefox and chrome (both from the server itself and from a remote machine

相关标签:
6条回答
  • 2020-12-31 10:44

    I have resolved the said

    javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names matching IP address

    error by adding one alternative subject name (DNS) in the server certificate (having CN=example.com) which after prints the part of certificate as below:

    Subject Alternative Name:
    DNS: example.com
    

    I used KeyExplorer on windows for generating my server certificate. You can follow this link for adding alternative subject names (follow the only part for adding it).

    0 讨论(0)
  • 2020-12-31 10:47

    Your certificate should include that ip value as a subject alternative name value (of type IPAddress : key=7).

    http://web.archive.org/web/20160201235032/http://www.jroller.com/hasant/entry/no_subject_alternative_names_matching

    0 讨论(0)
  • 2020-12-31 10:47

    Execute the following steps

    1- Modify the file: /etc/ssl/openssl.cnf, for example:

    subjectAltName=DNS:api.electoralsystem
    

    2- Generate private key

    jmendoza@jmendoza:~$ openssl genrsa -aes256 -out electoralsystem-cakey.pem 2048 -alias electoralsystem-cakey.pem
    Generating RSA private key, 2048 bit long modulus
    ....................+++++
    .......................................+++++
    e is 65537 (0x010001)
    Enter pass phrase for electoralsystem-cakey.pem:
    Verifying - Enter pass phrase for electoralsystem-cakey.pem:
    

    3- Generate cacert x509

    jmendoza@jmendoza:~$ openssl req -new -x509 -sha256 -key electoralsystem-cakey.pem -days 365 -out electoralsystem-cacert.pem 
    Enter pass phrase for electoralsystem-cakey.pem:
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    Country Name (2 letter code) [AU]:VE
    State or Province Name (full name) [Some-State]:CARACAS
    Locality Name (eg, city) []:CARACAS
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:JMENDOZA
    Organizational Unit Name (eg, section) []:TI
    Common Name (e.g. server FQDN or YOUR name) []:api.electoralsystem
    Email Address []:xxxx@gmail.com 
    

    openssl x509 -in electoralsystem-cacert.pem -text

    4- Generate keystore pkcs12

    jmendoza@jmendoza:~$ openssl pkcs12 -export -in electoralsystem-cacert.pem -inkey electoralsystem-cakey.pem -out electoralsystem-store.p12 -name "electoralsystem-store" 
    Enter pass phrase for electoralsystem-cakey.pem:
    Enter Export Password:
    Verifying - Enter Export Password:
    

    5- If you need it, convert the PKCS12 keystore to JKS keytstore using keytool command

    jmendoza@jmendoza:~$ keytool -importkeystore -destkeystore electoralsystem-store.jks -deststorepass jmendoza -srckeystore electoralsystem-store.p12 -srcstoretype PKCS12 -srcstorepass jmendoza -alias electoralsystem-store
    Importando el almacén de claves de electoralsystem-store.p12 a electoralsystem-store.jks...
    

    6- On the client, import certificate in keytstore

    jmendoza@jmendoza:~$ keytool -importcert -file electoralsystem-cacert.pem -keystore ldap-server-smmt.jks 
    Introduzca la contraseña del almacén de claves:
    

    Import certificate in keytstore

    Invoke API - https://api.electoralsystem:8081/yyyy/xxxxx

    7- Configure certificates on the api server

    Configure certificates on the api server

    8- Summary generated files

    jmendoza@jmendoza:~$ ls -lt
    total 1332
    -rw-rw-r--  1 jmendoza jmendoza    2482 jul 25 10:15  ldap-server-smmt.jks
    -rw-r--r--  1 jmendoza jmendoza    2442 jul 25 10:04  electoralsystem-store.jks
    -rw-------  1 jmendoza jmendoza    2792 jul 25 10:01  electoralsystem-store.p12
    -rw-r--r--  1 jmendoza jmendoza    1509 jul 25 09:45  electoralsystem-cacert.pem
    -rw-------  1 jmendoza jmendoza    1766 jul 25 09:38  electoralsystem-cakey.pem
    

    Note: configure DNS api.electoralsystem on the client's docker or server

    0 讨论(0)
  • 2020-12-31 10:48

    The reason, we get above error is that CN(Common name) defined in your certificate is not matching with the domain the application is running on. For e.g, In your certificate, the CN name is defined as www.example.com or an IP but you may be running the application say a URL which is like http://localhost:8080/api

    So to fix the above error simply use one of the below approaches

    Run the application on the same ‘CN’, as defined in your certificates.

    OR

    Along with CN name you can add Subject alt names in your certificate, which is like adding more than one domain in the certificate. Link below describes the process of adding multiple domains(subject-alt-name) to jks file and also to a certificate.

    Follow this link: Learn how to add subject alt names and resolve the above error

    0 讨论(0)
  • 2020-12-31 10:58

    I have solved the issue using 3 Steps

    1. Creating a class . The class has some empty implementations

      class MyTrustManager implements X509TrustManager 
      {
      public java.security.cert.X509Certificate[] getAcceptedIssuers() {
         return null;
      }
      
      public void checkClientTrusted(X509Certificate[] certs, String authType) {
      }
      
      public void checkServerTrusted(X509Certificate[] certs, String authType) {
      }
      
      @Override
       public void checkClientTrusted(java.security.cert.X509Certificate[]      paramArrayOfX509Certificate, String paramString)
          throws CertificateException {
        // TODO Auto-generated method stub
      
      }
      
      @Override
      public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString)
              throws CertificateException {
          // TODO Auto-generated method stub
      
      }
      
    2. Creating a method

      private static void disableSSL() {
            try {
               TrustManager[] trustAllCerts = new TrustManager[] { new   MyTrustManager() };
      
          // Install the all-trusting trust manager
          SSLContext sc = SSLContext.getInstance("SSL");
          sc.init(null, trustAllCerts, new java.security.SecureRandom());
          HostnameVerifier allHostsValid = new HostnameVerifier() {
              public boolean verify(String hostname, SSLSession session) {
                  return true;
              }
          };
          HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
          HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
      } catch (Exception e) {
          e.printStackTrace();
      }}
      
    3. Call the disableSSL() method from where exception being thrown. It worked fine.

    0 讨论(0)
  • 2020-12-31 11:06

    The reason why this fails is because the hostname of the target endpoint and the certificate common name (CN in certification Subject does not match).

    For e.g., from a JVM, when trying to connect to an IP address (WW.XX.YY.ZZ) and not the DNS name (https://stackoverflow.com), the HTTPS connection will fail because the certificate stored in the java truststore cacerts expects common name to match the target address.

    To mitigate this HostnameVerifier needs to be verify the connection despite the mismatch https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#HostnameVerifier

        HttpsURLConnection urlConnection = (HttpsURLConnection) new URL("https://test.test/api").openConnection();
        urlConnection.setSSLSocketFactory(buildSocketFactory());
        urlConnection.setDoOutput(true);
        urlConnection.setRequestMethod("get");
        urlConnection.setHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession sslSession) {
                return true;
            }
        });
        urlConnection.getOutputStream();
    
    0 讨论(0)
提交回复
热议问题