Custom Implementation of Trust Manager and Hostname Verifier

465 Views Asked by At

I am making post request to a third party service setting the hostname verifier and trust manager. The default pass all implementation however doesn't pass sonarcloud checks and gives errors which are attached in screenshots below. Have browsed for hours searching for custom implementation but haven't found anything. Please suggest of any resources or implementation you may have with yourself. Here is the code for the same:

public static class DummyTrustManager implements X509TrustManager {

        public DummyTrustManager() {
        }

        public boolean isClientTrusted(X509Certificate cert[]) {
            return true;
        }

        public boolean isServerTrusted(X509Certificate cert[]) {
            return true;
        }

        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }

        public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {

        }

        public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {

        }
    }

    public static class DummyHostnameVerifier implements HostnameVerifier {

        public boolean verify(String urlHostname, String certHostname) {
            return true;
        }

        public boolean verify(String arg0, SSLSession arg1) {
            return true;
        }
    }

    public String nsdlResponseLine(String data, String signature){

        String line = null;
        try {
            String urlOfNsdl = nsdlKycVerificationUrl;
            final String version = nsdlKycVerificationVersion;
            SSLContext sslcontext = SSLContext.getInstance("TLSv1.2");
            sslcontext.init(new KeyManager[0],
                    new TrustManager[]{new DummyTrustManager()},
                    new SecureRandom());
            SSLSocketFactory factory = sslcontext.getSocketFactory();
            String urlParameters = getUrlParameters(data, signature, version);
            URL url = new URL(urlOfNsdl);

            connection = (HttpsURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            connection.setRequestProperty("Content-Length", "" + Integer.toString(urlParameters.getBytes().length));
            connection.setRequestProperty("Content-Language", "en-US");
            connection.setUseCaches(false);
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setSSLSocketFactory(factory);
            connection.setHostnameVerifier(new DummyHostnameVerifier());
            OutputStream os = connection.getOutputStream();
            OutputStreamWriter osw = new OutputStreamWriter(os);
            osw.write(urlParameters);
            osw.flush();
            osw.close();

            InputStream is = connection.getInputStream();
            BufferedReader in = new BufferedReader(new InputStreamReader(is));
            line = in.readLine();
            is.close();
            in.close();
        } catch (Exception e) {
            log.debug("::Exception: {}",e.getMessage());
        }
        return line;
    }

    private String getUrlParameters(String data, String signature, String version) throws UnsupportedEncodingException {
        return "data=" + URLEncoder.encode(data, "UTF-8") + "&signature=" + URLEncoder.encode(signature, "UTF-8") + "&version=" + URLEncoder.encode(version, "UTF-8");
    }

Errors which come in Sonarcloud: enter image description here

1: enter image description herehttps://i.stack.imgur.com/y5qWJ.png

1

There are 1 best solutions below

0
On

ChatGPT came to rescue and solved the issue. I used default JSSE implementation for both. For sslcontext How do I provide a specific TrustStore while using the default KeyStore in Java (JSSE) ,this answer served as guiding light while for hostname verifier HttpsURLConnection.getDefaultHostnameVerifier() method can be used. My final code looks like this:

 public String nsdlResponseLine(String data, String signature){

        String line = null;
        try {
            String urlOfNsdl = nsdlKycVerificationUrl;
            final String version = nsdlKycVerificationVersion;
            SSLContext  sslcontext = SSLContext.getInstance("TLSv1.2");
            String  keyStore = System.getProperty("javax.net.ssl.keyStore");
            String  keyStoreType = System.getProperty("javax.net.ssl.keyStoreType", KeyStore.getDefaultType());
            String  keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword","");
            KeyManager[]    kms = null;
            if (keyStore != null) {
                KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
                KeyStore ks = KeyStore.getInstance(keyStoreType);
                if (keyStore != null && !keyStore.equals("NONE")) {
                    FileInputStream fs = new FileInputStream(keyStore);
                    ks.load(fs, keyStorePassword.toCharArray());
                    if (fs != null)
                        fs.close();
                    char[] password = null;
                    if (keyStorePassword.length() > 0)
                        password = keyStorePassword.toCharArray();
                    kmf.init(ks, password);
                    kms = kmf.getKeyManagers();
                }
                sslcontext.init(kms, null, null);
            }

            SSLSocketFactory factory = sslcontext.getSocketFactory();
            String urlParameters = getUrlParameters(data, signature, version);
            URL url = new URL(urlOfNsdl);

            HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            connection.setRequestProperty("Content-Length", "" + Integer.toString(urlParameters.getBytes().length));
            connection.setRequestProperty("Content-Language", "en-US");
            connection.setUseCaches(false);
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setSSLSocketFactory(factory);
            connection.setHostnameVerifier(HttpsURLConnection.getDefaultHostnameVerifier());
            OutputStream os = connection.getOutputStream();
            OutputStreamWriter osw = new OutputStreamWriter(os);
            osw.write(urlParameters);
            osw.flush();
            osw.close();

            InputStream is = connection.getInputStream();
            BufferedReader in = new BufferedReader(new InputStreamReader(is));
            line = in.readLine();
            is.close();
            in.close();
        } catch (Exception e) {
            log.debug("::Exception: {}",e.getMessage());
        }
        log.debug("line;{}",line);
        return line;
    }

    private String getUrlParameters(String data, String signature, String version) throws UnsupportedEncodingException {
        return "data=" + URLEncoder.encode(data, "UTF-8") + "&signature=" + URLEncoder.encode(signature, "UTF-8") + "&version=" + URLEncoder.encode(version, "UTF-8");
    }