Skip to main content

Select TLS Cipher Suites (Java)

When using TLS encryption with Aerospike Database Enterprise Edition (the server), Aerospike recommends that you explicitly specify the set of cipher suites to use during the TLS handshake. This ensures that the cipher suites that get the best performance are used, while satisfying your organization’s security requirements.

This is especially important with JVM-based applications because the default cipher suite list can vary between JVM environments, which may result in the application negotiating a cipher suite which has poor performance or weaker security.

Unlike public-facing servers like websites and web services, the server is generally deployed in an environment where the TLS client (the application) and the TLS server (Aerospike server) are both controlled by the same entity. In this kind of environment the list of supported cipher suites can be much more specific.

For example, we'll assume that an organization has identified the following four cipher suites as optimal in terms of security and performance:

  1. TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  2. TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
  3. TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  4. TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

There are two ways to ensure that Java applications use and prioritize this list in the specified order:

  • Specify the allowed cipher suites in the Aerospike configuration.
  • Specify the allowed cipher suites in Java applications.

These two approaches are not mutually exclusive. It is possible to use the Aerospike configuration to enforce the broadest set of acceptable ciphers and then further narrow the list direcly in applications that have specific requirements.

note

Aerospike recommends that you always specify at least one cipher suite list in the Aerospike configuration, excluding cipher suites which do not meet security or performance requirements.

Specifying cipher suites in the Aerospike configuration

You can specify a list of allowed cipher suites with the

cipher-suitedirective. However, because the server uses OpenSSL, the cipher suite name must be mapped from the [IANA notation](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml) that Java uses to the OpenSSL notation that Aerospike uses.
OpenSSL (Aerospike)IANA (Java)
ECDHE-ECDSA-AES128-GCM-SHA256TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
ECDHE-ECDSA-AES256-GCM-SHA384TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
ECDHE-RSA-AES128-GCM-SHA256TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
ECDHE-RSA-AES256-GCM-SHA384TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

The following example aerospike.conf configuration shows only the stanzas and directives that are relevant for the cipher suite configuration:

network {
tls example.server {
cipher-suite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384
}
}

Specifying cipher suites in Java applications

You can specify a list of allowed cipher suites in the Aerospike Java Client in the TlsPolicy attached to the ClientPolicy. For example, assume a new security policy requires all new applications to only use AES256, but the server still needs to accept AES128 ciphers from legacy applications.

New applications can further restrict the 4 cipher suites the server uses to just the AES256 variants:

ClientPolicy policy = new ClientPolicy();
policy.tlsPolicy = new TlsPolicy();

String[] ciphers = {
// IANA (Java) OpenSSL (Aerospike Server)
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", // ECDHE-ECDSA-AES256-GCM-SHA384
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" // ECDHE-RSA-AES256-GCM-SHA384
};
policy.tlsPolicy.ciphers = ciphers;

Troubleshooting tips

To see which cipher suites your Java environment supports and the order of priority, use the getSupportedCipherSuites() method of the javax.net.ssl.SSLSocketFactory object for the default SSL context. If jrunscript is available on the client nodes, you can run the following one-liner from the command line:

jrunscript -e "java.util.Arrays.asList(javax.net.ssl.SSLContext.getDefault().getSocketFactory().getSupportedCipherSuites()).forEach(println)"

Alternatively, you can use the following Java command-line application:

package com.aerospike.examples;

import javax.net.ssl.SSLContext;
import java.security.NoSuchAlgorithmException;

public class Main {

public static void main(String[] args) {

System.out.println("Supported Cipher Suites:");

try {
String[] ciphers = SSLContext.getDefault().getSocketFactory().getSupportedCipherSuites();
for (int i = 1; i < ciphers.length; i++) {
System.out.println(" " + i + ". " + ciphers[i]);
}
} catch (NoSuchAlgorithmException e) {
System.out.println("Failed to get default SSL context.");
}
}
}
note

Many versions of the JDK prioritized CBC cipher suites over GCM ciphers. This is a common cause of poor performance. If the output of the above scripts show CBC cipher suites before the GCM cipher suites, it’s especially important to explicitly select the allowed cipher suites.

Check available ciphers from a client node

The nmap command determines which cipher suites are available to the client with the ssl-enum-ciphers script. This script probes the server node from a client application.

These examples configure the server to allow 4 ciphers;. Two of those ciphers are based on RSA-based certificates and the other 2 are based on ECDSA-based certificates. Which of the 4 cipher suites can be used depends on the type of certificate installed on the server nodes.

Assuming the server nodes have an ECDSA certificate, the output of the following command shows that only the 2 ECDSA-based certificates are available to the client as acceptable cipher suites.

nmap --script ssl-enum-ciphers -Pn -p 4000 192.168.105.20

Example output:

Starting Nmap 7.70 ( https://nmap.org ) at 2020-04-06 22:52 UTC
Nmap scan report for 192.168.105.20
Host is up (0.00046s latency).

PORT STATE SERVICE
4000/tcp open remoteanything
| ssl-enum-ciphers:
| TLSv1.2:
| ciphers:
| TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A
| TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A
| compressors:
| NULL
| cipher preference: server
|_ least strength: A

Nmap done: 1 IP address (1 host up) scanned in 0.22 seconds

Debug the TLS Handshake in Java

If a Java application is not able to connect to an Aerospike cluster over TLS which you believe is configured correctly, you can pass the javax.net.debug argument to the JVM when invoking the application to enable verbose logging of each step of the TLS handshake. For example:

java -Djavax.net.debug=all -jar MyApplication.jar