Sterling Managed File Transfer

Sterling Managed File Transfer

Come for answers, stay for best practices. All we're missing is you.

 View Only

Tool to verify supported ciphers in IBM Sterling B2B Integrator

By Tanvi Kakodkar posted Mon February 17, 2020 10:27 AM

  
Originally updated on January 10, 2018 by BipinChandra

Written & Reviewed By: Janardhan A Naidu & Bipin Chandra

 

Introduction:

Cipher suite is a concept used in Transport Layer Security (TLS) / Secure Sockets Layer (SSL) network protocol. A cipher suite is a named combination of authentication, encryption, message authentication code (MAC) and key exchange algorithms used to negotiate the security settings basically in SSL handshake.

There are so many Cipher Suites available and customer/s uses them to build their solutions. Many a time there is a need to identify or check if the Ciphers customers are using are really supported by Sterling Integrator or not.

This article helps such customers to make use of this tool, pass the required information listed in this article and verify if the Cipher they intend to use is supported or not by the product.

This tool is a java application. Read below to understand the same.


How to use this tool:

Download the tool -> CipherSuiteEnsure.zip (See attachment tab below). Unzip it, the directory structure will look like this:

Mention the Cipher Suite name which needs to be tested in testing.properties file, if there are no ciphers in the properties file then it will be pick up the default cipher from client side jdk. You can add a list of ciphers in comma separated. If 'defaultCipher' is mentioned then client side will restrict the ciphers to these many only.

For example:

defaultCipher=TLS_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256

Optional but recommended: User should also add the ‘Unrestricted Policy jar’ into the [java home] jre/lib/security directory, which enables JDK to support all the Cipher Suites.

 

USAGE:

Open the console and execute it as follows:

$ java –jar CipherTest.jar –host <hostname> -port <port numer> -passphrase <(optional) passphrase> -cipherSuitePropertyFileLocaiton <location of property file>

NOTE:

Host: server host name

Port: https port

Passphrase: password which is optional

cipherSuitePropertyFileLocation: location of the property file along with file name, extension of the file name should be .properties and the file should contain a property called “defaultCipher” and the value is the cipher suite names which needs to be tested. In example above we have kept it as testing.properties, but user can have their own name for this properties file.

 

 

Steps to run:

  1. Extract CipherSuiteEnsure.zip to the working directory.
  2. Edit testing.properties file by adding the required ciphes to be tested into “defaultCiphers” property.
  3. Open the command prompt and direct into the working directory where the CipherSuiteEnsure.zip file is extracted.
  4. Add the unrestricted policy jars into jre/lib/security directory (for supporting more ciphers in client side) – optional.
  5. Run the below command in command prompt -

$java –jar CipherTest.jar –host <hostname> -port <port numer> -passphrase <(optional) passphrase> -cipherSuitePropertyFileLocaiton <location of property file>

 

For example:

$ java –jar CipherTest.jar –host host.ibm.com -port 1234 -cipherSuitePropertyFileLocaiton testing.properties

 

JAVA Client Implementation:

 

Creating jssecacerts: Creating a jssecacerts file in working directory if it is not present. This file is used to store the required certificates and keystore which are required for communication.

        File file = new File("jssecacerts");

        if (file.isFile() == false) {

            char SEP = File.separatorChar;

            File dir = new File(System.getProperty("java.home") + SEP

                    + "lib" + SEP + "security");

            file = new File(dir, "jssecacerts");

            if (file.isFile() == false) {

                file = new File(dir, "cacerts");

            }

        }

 

Loading the Keystore from a file: Creating the keystore object and loading the keys and certificates which are in file.

InputStream in = new FileInputStream(file);

          KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());

          ks.load(in, passphrase);

          in.close();

 

Creating SSLContext object: creating a SSL context object for TLS protocol, and trust manager object. Trust manager object is initialized using keystore; ssl context object is initialized using the trust manager object.

  SSLContext context = SSLContext.getInstance("TLS");

        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

        tmf.init(ks);

        X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];

        SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);

        context.init(null, new TrustManager[]{tm}, null);

        SSLSocketFactory factory = context.getSocketFactory();

 

Loading the Property file: here we are loading the property file which contains the list of cipher suites under defaultCipher property which needs to be tested

try {
            input = new FileInputStream(path);
            prop.load(input);
            if(prop.getProperty("defaultCipher")!=null){
                CipherList =     prop.getProperty("defaultCipher").split(",");

            } else {
                System.out.println("There is not property called defaultCipher in the given properties file. "
                        + "Please add this property into the file with the cipher name ");
                return;
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

 

Creating SSLSocket Object: Creating the SSLSocket object for specified host and port, enabling the required protocols and cipher suite which are mentioned in properties file one by one and performing handshake.

SSLSocket socket = (SSLSocket)factory.createSocket(host, port);

                        socket.setEnabledProtocols(new String[]{"TLSv1","TLSv1.1","TLSv1.2"});

                        .setSoTimeout(10000);

                        socket.setEnabledCipherSuites(new String[] {x});                                 

                        socket.startHandshake();

 

Printing result: here we are printing the supported and unsupported ciphers. 

System.out.println("Supported Ciphers:");

       for(String SC:SuccessCiphers){

                System.out.println(SC);

            }

            System.out.println("UnSupported Ciphers:");

            for(String FC:FailureCiphers){

                System.out.println(FC);     

                }

 

Adding the certificates into file: adding certificates and keystore required for communication into file called jssecacerts which is already created.

           X509Certificate cert = chain[k];

        String alias = host + "-" + (k + 1);

        ks.setCertificateEntry(alias, cert);

        OutputStream out = new FileOutputStream("jssecacerts");

        ks.store(out, passphrase);

        out.close();

 

Source Code:

package com.sterlingcommerce.devtest;

 

import javax.net.ssl.*;

import java.io.*;

import java.security.KeyStore;

import java.security.MessageDigest;

import java.security.cert.CertificateException;

import java.security.cert.X509Certificate;

import java.util.ArrayList;

import java.util.List;

import java.util.Properties;

 

/**

 * Class used to add the server's certificate to the KeyStore

 * with your trusted certificates.

 */

public class CipherTest {

    public static void main(String[] args) throws Exception {

        String host = null;

        int port = 0;

        char[] passphrase = "changeit".toCharArray();

        String path = null;

        int j=0;

        while(j<args.length){

            if(args[j].startsWith("-")){

                if(args[j].equalsIgnoreCase("-host")){

                        host=args[j+1];

            } else if(args[j].equalsIgnoreCase("-port")) {

                        port=Integer.parseInt(args[j+1]);

            } else if(args[j].equalsIgnoreCase("-passphrase")){

                        passphrase=args[j+1].toCharArray();

            } else if(args[j].equalsIgnoreCase("-cipherSuitePropertyFileLocation")) {

                        path=args[j+1];

            } else {

                        System.out.println("Invalid Values:"+args[j]);

                        System.out.println("Usage: java -host <host> -port <port> -cipherSuitePropertyFileLocation <file location along with file name> -passphrase <(optional) passphrase>");

            }

            j++;

        }

        if((args.length!=6 && args.length!=8) || host == null || path == null || port==0 ){

            System.out.println("Usage: java -host <host> -port <port> -cipherSuitePropertyFileLocation <file location along with file name> -passphrase <(optional) passphrase>");

            return;

        }

        if(!path.endsWith(".properties")){

            System.out.println("Path should contain the file name and file extension should be .properties");

            return;

        }

       

        File file = new File("jssecacerts");

        if (file.isFile() == false) {

            char SEP = File.separatorChar;

            File dir = new File(System.getProperty("java.home") + SEP + "lib" + SEP + "security");

            file = new File(dir, "jssecacerts");

            if (file.isFile() == false) {

                file = new File(dir, "cacerts");

            }

        }

        InputStream in = new FileInputStream(file);

        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());

        ks.load(in, passphrase);

        in.close();

 

        System.out.println("Ensuring the Cipher Support:");

        SSLContext context = SSLContext.getInstance("TLS");

        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

        tmf.init(ks);

        X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];

        SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);

        context.init(null, new TrustManager[]{tm}, null);

        SSLSocketFactory factory = context.getSocketFactory();

 

        System.out.println("Opening connection to " + host + ":" + port + "...");

 

         List<String> SuccessCiphers = new ArrayList<String>();

         List<String> FailureCiphers = new ArrayList<String>();

         String[] CipherList = null;

         System.out.println("Starting SSL handshake:");

               

         Properties prop = new Properties();

         InputStream input = null;

                       

          try {

              input = new FileInputStream(path);

              prop.load(input);

              if(prop.getProperty("defaultCipher")!=null) {

                  CipherList =   prop.getProperty("defaultCipher").split(",");

              } else {

                  System.out.println("There is not property called defaultCipher in the given properties file. "

                          + "Please add this property into the file with the cipher name ");

                  return;

              }

         } catch (IOException ex) {

               ex.printStackTrace();

         } finally {

               if (input != null) {

                    try {

                          input.close();

                   } catch (IOException e) {

                         e.printStackTrace();

                   }

          }

      }              

 

    for (String x: CipherList)

        try {

                 SSLSocket socket = (SSLSocket)factory.createSocket(host, port);

                 socket.setEnabledProtocols(new String[]{"TLSv1","TLSv1.1","TLSv1.2"});

                    socket.setSoTimeout(10000);

                            socket.setEnabledCipherSuites(new String[] {x});                                 

            socket.startHandshake();

            System.out.println("Cipher: "+socket.getSession().getCipherSuite()+" ---->Success");

            SuccessCiphers.add(socket.getSession().getCipherSuite());

            socket.close();

        } catch (SSLException e) {

                System.out.println("Cipher: "+x+" ---->Failed");

                FailureCiphers.add(x);

        }

                System.out.println();

                 System.out.println("Supported Ciphers:");

                 for(String SC:SuccessCiphers){

                             System.out.println(SC);

                 }

                 System.out.println();

                 System.out.println("UnSupported Ciphers:");

                 for(String FC:FailureCiphers){

                             System.out.println(FC);     

                }

        X509Certificate[] chain = tm.chain;

        if (chain == null) {

            System.out.println("Could not obtain server certificate chain");

            return;

        }

 

       MessageDigest sha1 = MessageDigest.getInstance("SHA1");

        MessageDigest md5 = MessageDigest.getInstance("MD5");

        for (int i = 0; i < chain.length; i++) {

            X509Certificate cert = chain[i];

            sha1.update(cert.getEncoded());

            md5.update(cert.getEncoded());

       }

 

        int k=0;

        X509Certificate cert = chain[k];

        String alias = host + "-" + (k + 1);

        ks.setCertificateEntry(alias, cert);

        OutputStream out = new FileOutputStream("jssecacerts");

        ks.store(out, passphrase);

        out.close();

    }

    private static class SavingTrustManager implements X509TrustManager {

        private final X509TrustManager tm;

        private X509Certificate[] chain;

        SavingTrustManager(X509TrustManager tm) {

            this.tm = tm;

        }

 

        public X509Certificate[] getAcceptedIssuers() {

            //throw new UnsupportedOperationException();

           return new X509Certificate[0];

        }

 

        public void checkClientTrusted(X509Certificate[] chain, String authType)

                throws CertificateException {

            throw new UnsupportedOperationException();

        }

 

        public void checkServerTrusted(X509Certificate[] chain, String authType)

                throws CertificateException {

            this.chain = chain;

            tm.checkServerTrusted(chain, authType);

        }

    }

}

 

Sample Results:

In the above screen we can see that we are testing with 3 ciphers in which 2nd cipher is success as it is supported by server, 1st and 3rd ciphers are failed because these ciphers are not supported by server side.

 

FAQ

Q) While running the cipher test, we are getting an error called Unsupported ciphersuite or java.lang.IllegalArgumentException  as shown in below snapshot. What could be the solution to overcome this error?

 

Solution:

This error is because the java which you are using may not support the ciphers which you are willing to test; in that case you need to add unrestricted cipher support in jre/lib/security directory which enables most of the ciphers in client side.

 

Reference:

https://en.wikipedia.org/wiki/Cipher_suite


#DataExchange
#IBMSterlingB2BIntegratorandIBMSterlingFileGatewayDevelopers
0 comments
72 views

Permalink