Article

Building a keystore file to be used with an HTTPS (or ENCRYPTED) connection type for real-time Java-based APIs

Nipat Kunvutipongsak
Senior Software Engineer Senior Software Engineer

Introduction

Overview

Update: February 2021

Refinitiv Real-Time SDK  (i.e. EMA and ETA APIs, formerly known as Elektron SDK) supports various transport types. One of the most familiar connection types is ‘Socket Transport (RSSL)’ that implemented the idea of TCP/IP-based (RFC 971) reliable network protocol which is a packet-switch network. For two hosts to communicate (source and destination), they must packetize their data and submit it to communication devices to reach the end-point machine.

As a packet can and probably will pass through many routers (and network components) between the sender and receiver. If the contents of the data in that packet are sensitive – authentication information, confidential insider data – the sender would probably like to ensure that only the receiver can read the package, rather than the packet being readable by any router along the way. Secure Sockets Layer (SSL) and Transport Layer Security (TLS) are developed in order to serve this purpose in the HTTPS protocol.

HTTPS is vital to securing end-to-end interactions. For many server application, HTTPS is handled by the server side such as the Web server, Refinitiv Real-Time Distribution System component (ADS) integrated with SSL Accelerator. However, the client side needs its own HTTPS implementation to make requests and to receive information securely from the server. Fortunately, Real-Time SDK Java prepares a solution for you to use the keystore file.

This article will demonstrate how to generate a new keystore file, view the keystore file’s content, import a certification along with EMA Java API walkthrough.

Target Audience

This article provides information and examples that aids programmers using Real-Time  APIs (EMA and ETA) - Java Edition. It is assumed that the reader is familiar with running EMA or ETA application to connect to a provider application (or Refiniti Real-Time/RDF-D/ADS) before, and has experience developing products using the Java programming language in a networked environment.

What is the Keystore File

The keystore file (.jsk) contains the server’s certification, including its private key which is used for cryptographic. The keystore file is protected with a password. Each keystore entry has a unique alias that refers to a particular certificate. You can administrate the keystore file using “keytool – Key and Certificate Management Tool” provided by Oracle.

An RSSL consumer (client-server) diagram

For the connection and component topology that is used in this article, the consumer application connects to Refinitiv Real-Time Advanced Distribution Server via the Internet. The SSL accelerator is a server-side device located at the same Real-Time Advanced Distribution Server machine that helps to perform key and certificate exchange for HTTPS connection establishment.

Referring to the diagram above, if the EMA Java consumer tries to connect to the server without performing TLS handshake (RSSL_SOCKET or RSSL_HTTP), there will be no response from the server side (or encountering unexpected error) because it cannot understand a bare message, and expects a cipher message to be decrypted. 

    	
            

<!-- ChannelType possible values are:    -->

<!-- ChannelType::RSSL_SOCKET    - TCP IP connection type        -->

<!-- ChannelType::RSSL_HTTP      - Http tunnel connection type    -->

<!-- ChannelType::RSSL_ENCRYPTED - Https tunnel connection type    -->

<Channel>

    <Name value="Channel_4"/>

    <ChannelType value="ChannelType::RSSL_HTTP"/>

    <CompressionType value="CompressionType::None"/>

    <GuaranteedOutputBuffers value="5000"/>

    <Host value="server_host"/>

    <Port value="14002"/>

    <ObjectName value=""/>

</Channel>

So, you need to specify a connection channel type to RSSL_ENCRYPTED when the server requires SSL or TLS encryption. 

    	
            

<Channel>

    <Name value="Channel_4"/>

    <ChannelType value="ChannelType::RSSL_ENCRYPTED"/>

    <CompressionType value="CompressionType::None"/>

    <GuaranteedOutputBuffers value="5000"/>

    <Host value="server_host"/>

    <Port value="443"/>

    <ObjectName value=""/>

</Channel>

EMA Java API also provides a set of configuration for settings associated to the keystore file (refer to Chapter 4.3.2: Tunneling Configuration of the EMA Java developer guide). Below are some interfaces of an OmmConsumerConfig class to specify security parameters:

Method Description
tunnelingKeyStoreFile(java.lang.String keyStoreFile)
The key store file that contains your own private keys, and public key certificates you received from someone else.
tunnelingKeyStorePasswd(java.lang.String keyStorePasswd)
The passwd for the key store file.
tunnelingKeyStoreType(java.lang.String keyStoreType)
The type of the key store for certificate file.

Here this is the example usage to specify the keystore file and keystore password.

    	
            

// Create an OMM consumer

OmmConsumer consumer = EmaFactory.createOmmConsumer(EmaFactory.createOmmConsumerConfig()

    .consumerName("Consumer_3")

    .tunnelingKeyStoreFile("KEYSTORE_FILENAME")

    .tunnelingKeyStorePasswd("KEYSTORE_PASSWORD")

    );

Generate your Keystore file using Oracle's keytool

 

You can find the keytool program from a bin subfolder of a Java Developer Kit (JDK) installation folder (in the same location as javac). The keytool program is a command-line based application, so you need to run it using command-prompt.

Use the following command to create a new keystore file

    	
            keytool -genkey -alias <ALIAS> -keyalg RSA -keystore <KEYSTORE_FILENAME> -storepass <PASSWORD>
        
        
    


The new keystore file has been created under the current working directory.

Remark: The option -genkey is the old name, but it is still supported in Java 8 release. However, the new name, -genkeypair is preferred going forward.

 

View Content in the Keystore File

You can view information (and certificate, which there is no any certificate data in the new file yet) using the following command:

    	
            keytool.exe -list -v -keystore <KEYSTORE_FILENAME> -storepass <PASSWORD>
        
        
    


As this is the new keystore file, it does not contain any server’s certificate yet. If you try to use it, the application will receive an event indicates that it cannot initialize a channel, which is not sufficient information (see below).

    	
            

Feb 11, 2021 11:03:02 AM com.refinitiv.ema.access.ChannelCallbackClient reactorChannelEventCallback

WARNING: loggerMsg

    ClientName: ChannelCallbackClient

    Severity: Warning

    Text:    Received ChannelDownReconnecting event on channel Channel_4

    RsslReactor Channel is null

    Error Id 0

    Internal sysError 0

    Error Location Reactor.processWorkerEvent

    Error text Error initializing channel: errorId=0 text=null

loggerMsgEnd

At this stage, you can use the JVM argument option: -Djavax.net.debug=all to print more detail of HTTPS activities. Please see the example below:

    	
            java -Djavax.net.debug=all -Djava.util.logging.config.file=logging.properties -cp <CLASSPATH> <APPLICATION_NAME>
        
        
    

Here this is the log output after adding the JVM parameter above:

    	
            

<SSL Handshake Information>

***

pool-1-thread-1, fatal error: 46: General SSLEngine problem

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

%% Invalidated:  [Session-1, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384]

pool-1-thread-1, SEND TLSv1.2 ALERT:  fatal, description = certificate_unknown

pool-1-thread-1, WRITE: TLSv1.2 Alert, length = 2

pool-1-thread-1, fatal: engine already closed.  Rethrowing javax.net.ssl.SSLHandshakeException: General SSLEngine problem

pool-1-thread-1, called closeOutbound()

pool-1-thread-1, closeOutboundInternal()

Import a certificate into your keystore file

As the client requires the keystore file with the registered certification from the server (for encryption), you may search for the server certificate using in the log output. According to our test environment (see below), it conveys that our server is using an “http://cacerts.digicert.com/DigiCertSHA2SecureServerCA.crt” during an SSL handshake stage.

*** Important updated on October 2018: The TRCC servers now use a certificate from comodo, please download it from "http://crt.comodoca.com/COMODORSAOrganizationValidationSecureServerCA.crt" instead. ***

    	
            

<THIS IS THE EXAMPLE OF AN OUTPUT FROM SERVERS THAT USE DIGICERT when a -Djavax.net.debug=all JVM option is enabled>

...

[2]: ObjectId: 1.3.6.1.5.5.7.1.1 Criticality=false

AuthorityInfoAccess [

  [

   accessMethod: ocsp

   accessLocation: URIName: http://ocsp.digicert.com

   accessMethod: caIssuers

   accessLocation: URIName: http://cacerts.digicert.com/DigiCertSHA2SecureServerCA.crt

]

]

 

 

<THIS IS THE EXAMPLE OF AN OUTPUT FROM SERVERS THAT USE COMODO CA when a -Djavax.net.debug=all JVM option is enabled>

[2]: ObjectId: 1.3.6.1.5.5.7.1.1 Criticality=false

AuthorityInfoAccess [

  [

   accessMethod: caIssuers

   accessLocation: URIName: http://crt.comodoca.com/COMODORSAOrganizationValidationSecureServerCA.crt

   accessMethod: ocsp

   accessLocation: URIName: http://ocsp.comodoca.com

]

]

So, you need to download this certification to your local machine (depending on which certificate that the server in your environment is using by referring to the link shown in the HTTPS/SSL or HTTPS/TLS tracing log output). After that, you can use the keytool to view and verify the content of the certification obtained using the following command:

    	
            keytool -printcert -v -file <CERTIFICATE_FILENAME>
        
        
    

Note: You do not have to get every certificate, just only the certificate that appears in the output during the SSL or TLS handshake stage).

The example outputs form various certifications:

Digicert Comodo CA


To import the certification obtained into the keystore file, use the command below.

    	
            keytool -import -trustcacerts -alias <NEW_ALIAS> -file <CERTFICICATE_FILENAME> -keystore <KEYSTORE_FILENAME> -storepass <PASSWORD>
        
        
    

Here there are example screenshots when importing the certificate files:

 

Digicert Comodo CA


Remark: The option -import is the old name but it is still supported in Java 8 release. However, the new name, -importcert is preferred going forward.

You can also re-check whether the certificate was added in the keystore file successfully or not using the same command in the previous step (and specify an alias option to filter the output if necessary).

    	
            keytool -list -v -keystore <KEYSTORE_FILENAME> -storepass <PASSWORD> -alias <ALIAS>
        
        
    

Below are the outputs after certification import:

Digicert Comodo CA


After the server certificate has been entrusted within the keystore file. Now, the keystore file is ready to be used via encrypted connection type. Below is the success log output from EMA Java API.

    	
            

Feb 11, 2021 11:04:33 AM com.refinitiv.ema.access.ChannelCallbackClient reactorChannelEventCallback

INFO: loggerMsg

    ClientName: ChannelCallbackClient

    Severity: Info

    Text:    Received ChannelUp event on channel Channel_4

    Instance Name Consumer_3_1

    Component Version ads3.4.2.L1.linux.tis.rrg 64-bit

loggerMsgEnd

Once the application can connect to the server and receive a response back. You can remove the JVM option to reduce the log overhead output.

More example from Enterprise Transport API (ETA) - Java

ETA Java provides methods to specify HTTPS tunneling by setting a ConnectionTypes.ENCRYPTED constant as an input of a ConnectOptions.connectionType() method. Also, it has a TunnelingInfo class to specify details of a keystore file using (refer to Chapter 9.15: Tunneling of the ETA Java developer guide).

Class Method Purpose Value
ConnectOptions connectionType(int connectionType) Type of connection to establish.
  • ConnectionTypes.ENCRYPTED
    • Indicates that the Channel is using an SSL/TLS encrypted HTTP TCP-based socket connection.
  • ConnectionTypes.HTTP
    • Indicates that the Channel is using an HTTP TCP-based socket connection.
  • ConnectionTypes.RELIABLE_MCAST
    • Indicates that the Channel is using a reliable multicast based connection.
  • ConnectionTypes.SEQUENCED_MCAST 
  • ConnectionTypes.SOCKET
    • Indicates that the Channel is using a standard TCP-based socket connection.
  • ConnectionTypes.UNIDIR_SHMEM
    • Indicates that the Channel is using a unidirectional shared memory connection.
tunnelingInfo() Tunneling connection parameters. Use this ConnectionOptions.tunnelingInfo() method to access TunnelingInfo's attributes/members.  
tunnelingType(java.lang.String tunnelingType) Tunneling type. Possible values are "None", http", or "encrypted" For HTTP Tunneling, tunnelingType has to be set to "http" or "encrypted"
TunnelingInfo KeystoreFile(java.lang.String KeystoreFile) Keystore file that contains your own private keys, and public key certificates you received from someone else. <ANY>
KeystorePasswd(java.lang.String KeystorePasswd) Password for keystore file. <ANY>

Example:

    	
            

// ConnectOptions cOpt = chnlInfo.connectOptions.connectionList().get(0).connectOptions();

cOpt.connectionType(ConnectionTypes.ENCRYPTED);

cOpt.tunnelingInfo().tunnelingType("encrypted");

cOpt.tunnelingInfo().KeystoreFile("<KEYSTORE_FILENAME>");

cOpt.tunnelingInfo().KeystorePasswd("<KEYSTORE_PASSWORD>");

Example of general errors when using HTTPS with the keystore file:

Please enable the JVM option: -Djavax.net.debug=all to reveal more details about the error regarding HTTPS handshake activity.

1. The keystore file could not be found.

Error Message:

 

    	
            IOException initializeTLS: Error when loading keystore from certificate file <KEYSTORE_FILENAME> (The system cannot find the file specified)
        
        
    
Resolution:

Verify that the value of KEYSTORE_FILENAME is correct or exists or not.

2. The keystore file's password is not correct.

Error Message:
    	
            IOException initializeTLS: Error when loading keystore from certificate file <KEYSTORE_FILENAME> (The system cannot find the file specified)
        
        
    
Resolution:

Verify that the exact KEYSTORE_PASSWORD value is correct or not by using the keytool application.

3. The keystore file does not contain a valid certification to connect to the server.

Error Message:
    	
            

***

pool-1-thread-1, fatal error: 46: General SSLEngine problem

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

%% Invalidated:  [Session-1, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384]

pool-1-thread-1, SEND TLSv1.2 ALERT:  fatal, description = certificate_unknown

pool-1-thread-1, WRITE: TLSv1.2 Alert, length = 2

pool-1-thread-1, fatal: engine already closed.  Rethrowing javax.net.ssl.SSLHandshakeException: General SSLEngine problem

pool-1-thread-1, called closeOutbound()

pool-1-thread-1, closeOutboundInternal()

Resolution:

Check the javax.net.debug output to find the certification required.

Note: JRE8 Update 91 and higher support DigiCert certificates. If you encounter problems with DigiCert certificates, upgrade to JRE8 Update 91 or higher.

 

Conclusion

After reading this article, we hope you can get the idea about how to connect your application to the server by the HTTPS connection type. The article also introduces the Oracle's keytool application which is used for manipulating the keystore file as Java technology uses the keystore file to be a repository of certifications for secured message communication. We also mention the -Djavax.net.debug=all JVM argument which is useful when the application encounters a problem during the HTTPS connection establishment stage. The output from the JVM argument will give a meaningful message and provide some insight to identify a root cause of the problem.

 

Reference:

For any questions related to this article or the Refinitiv Real-Time SDK Java page, please use the Developer Community Q&A Forum.