0750 JDBC and SSL TLS - microsoft/CSS_SQL_Networking_Tools GitHub Wiki

JDBC

Here you will find some information related to SSL/TLS handshake issues with the JDBC driver and how to enable TLS 1.2. Most of the configurations related to SSL/TLS encryption protocols are found in the Java Runtime Environment and not directly related to the JDBC driver itself.  

JDK/JRE Version

  Each version of the JDBC driver supports different versions of the Runtime:  

JDBC Driver Version JRE Versions JDBC API Version
7.4 1.8, 11, 12 4.2, 4.3 (partially)
7.2 1.8, 11 4.2, 4.3 (partially)
7.0 1.8, 10 4.2, 4.3 (partially)
6.4 1.7, 1.8, 1.9 4.1, 4.2, 4.3 (partially)
6.2 1.7, 1.8 4.1, 4.2
6.1 1.7, 1.8 4.1, 4.2
6.0 1.7, 1.8 4.1, 4.2
4.2 1.7, 1.8 4.1, 4.2
4.1 1.7 4.0
4.0 1.5, 1.6, 1.7 3.0, 4.0

Source: https://docs.microsoft.com/en-us/sql/connect/jdbc/microsoft-jdbc-driver-for-sql-server-support-matrix?view=sql-server-2017#java-and-jdbc-specification-support  

Default Encryption Protocol

Below is a table with the JDK versions and TLS versions supported by Oracle Java implementation:  

JDK 8
(March 2014 to present)
JDK 7
(July 2011 to present)
JDK 6
(2006 to end of public updates 2013)
TLS Protocols TLSv1.2 (default)
TLSv1.1
TLSv1
SSLv3
TLSv1.2
TLS1v1.1
TLSv1 (default)
SSLv3
TLSv1.2 (JDK 6 update 121) and above
TLS v1.1 (JDK 6 update 111 and above)
TLSv1 (default)
SSLv3
JSSE Ciphers Ciphers in JDK 8 Ciphers in JDK 7 Ciphers in JDK 6
Reference JDK 8 JSSE JDK 7 JSSE JDK 6 JSSE

Source: https://blogs.oracle.com/java-platform-group/diagnosing-tls,-ssl,-and-https

JDK 6 and 7 will use TLS 1.0 by default. To use TLS 1.2 by default and disable older protocols, the following configurations need to be performed in the Java Runtime configuration:

How to change the protocol version on client side

To change the default client-side TLS protocol version in the JDK, use the jdk.tls.client.protocols system property. This property was introduced to JDK 7 in 7u95 and to JDK 6 in 6u121.

To enable specific TLS protocols on the client, specify them in a comma-separated list within quotation marks; all other supported protocols are then disabled on the client. For example, if the value of this property is “TLSv1.1,TLSv1.2”, then the default protocol settings on the client for TLSv1.1 and TLSv1.2 are enabled on the client, while SSLv3, TLSv1, and SSLv2Hello are disabled on the client.

// Set the client default protocol versions to TLS 1.0, 1.1 and 1.2.

$ java ‑Djdk.tls.client.protocols=”TLSv1,TLSv1.1,TLSv1.2” myApp

// Set the client default protocol version to TLS 1.0.

$ java ‑Djdk.tls.client.protocols=”TLSv1” myApp

Note that the standard TLS protocol version names used in the JDK are SSLv3, TLSv1, TLSv1.1 and TLSv1.2.

So, in practice, the minimum versions required are JDK 7u95 and JDK 6u121.

Source: https://www.java.com/en/configure_crypto.html  

Cipher suites

Another thing to consider is the Cipher Suites available on the client and the server. The client and the server will negotiate and agree on a compatible cipher suite to use, if the two cannot agree on the cipher suite, the connection will return an error. This usually happens when connecting from an old server to a newer server, where the older server does not support the newer ciphers, and the newer system has disabled the older ciphers due to security reasons. 

Troubleshooting TLS handshake issues

  • Check the JDBC driver support matrix.  

  • Identify the version of the Java Runtime Environment being used:

    To find the currently installed version, run this command:
    **java -version**
    
    TLS 1.2 protocol requires the minimum JDK versions:
    
    JDK 6 Update 121
    JDK 7 Update 95
    
  • Confirm the JVM is configured to use TLS 1.2 by default.

    Section “How to change the protocol version on client side”: 
    https://www.java.com/en/configure_crypto.html 
    
  • Collect a network trace to understand if the handshake error might be caused by any incompatibility between the cipher suites available on the client and server.

    To start the network trace:
          1. Open a Cmd with Run as Administrator and execute the following command (change path accordingly):
             netsh trace start capture=yes scenario=netconnection tracefile=c:\temp\%computername%.etl filemode=circular maxSize=500MB
          2. Reproduce the issue.
          3. Stop the network trace:
             netsh trace stop
    
  • Enable JDBC Driver tracing Configure the application to enable JDBC driver tracing as described in the below article: https://docs.microsoft.com/en-us/sql/connect/jdbc/tracing-driver-operation?view=sql-server-ver15

    TIP: To avoid modifications to an application application, another alternative would be to create/use a test Java application that is enabled for JDBC tracing.
    
    Sample applications can be found at https://docs.microsoft.com/en-us/sql/connect/jdbc/connecting-and-retrieving-data?view=sql-server-ver15.
    
    Sample code to enable tracing:
    
    Handler fh = new FileHandler("JDBCClient.log");
    fh.setFormatter(new SimpleFormatter());
    fh.setLevel(Level.FINEST);
    Logger.getLogger("").addHandler(fh);
    Logger logger = Logger.getLogger("com.microsoft.sqlserver.jdbc");
    logger.setLevel(Level.FINEST);
    

 

  • Enable SSL debugging in the JVM   SSL debugging can generate a large amount of trace data, use with caution and preferably in the context of a sample application.

    Example Java arguments to enable tracing:
    -Djavax.net.debug=all
    -Djavax.net.debug=ssl,handshake
    
    More detailed information can be found here:
    
    https://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html#Debug
    https://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/ReadDebug.html
    https://access.redhat.com/solutions/973783
           
    

Known issues

 

  • Intermittent JDBC Connectivity issue – The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: SQL Server returned an incomplete response. The connection has been closed. (JDBC versions prior to 4.2) https://blogs.msdn.microsoft.com/dataaccesstechnologies/2016/11/30/intermittent-jdbc-connectivity-issue-the-driver-could-not-establish-a-secure-connection-to-sql-server-by-using-secure-sockets-layer-ssl-encryption-error-sql-server-returned-an-incomplete-respons/   
  • Error message java.lang.RuntimeException: Could not generate DH keypair   During the SSL handshake, the client and server will negotiate the cipher suite to use, the KeyExchangeAlgoritm is part of this negotiation, when the algorithm used is Diffie-Hellman, the key used will have a size defined by the server. The client and the server accept a range of sizes for this key. If the ranges are different, the key generated might have a size that is not accepted by the other machine, leading to this error. This error usually occurs when the client and the server have different configurations for the Diffie-Hellman key size range.  
  • Configuration and Default values for DH key size for Windows SCHANNEL: https://docs.microsoft.com/en-us/windows-server/security/tls/tls-registry-settings#keyexchangealgorithm---diffie-hellman-key-sizes https://support.microsoft.com/en-us/help/3174644/microsoft-security-advisory-updated-support-for-diffie-hellman-key-exc   Registry path: RSA: HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms\PKCS ClientMinKeyBitLength ClientMaxKeyBitLength Diffie-Hellman: HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms\Diffie-Hellman ClientMinKeyBitLength ClientMaxKeyBitLength ServerMinKeyBitLength    Configuration and Default values for DH key size for Java Applications:   Reference articles: https://www.java.com/en/configure_crypto.html https://www.java.com/en/jre-jdk-cryptoroadmap.html  
  • Change default key size of the AlgorithmParameterGenerator and KeyPairGenerator implementations from 1024 to 2048 bits   This change will update the JDK providers to use 2048 bits as the default key size for DSA, RSA, and DiffieHellman instead of 1024 bits when applications have not explicitly initialized the java.security.KeyPairGenerator and java.security.AlgorithmParameterGenerator objects with a key size.   To test this change download JDK 9.0.1, 8u151, 7u161, 6u171, or later and set the system property jdk.security.defaultKeySize with the algorithm and its desired default key size. For example, to test a DSA default keysize of 2048, specify "‑Djdk.security.defaultKeySize=DSA:2048" on the java command-line.  
  • Changing minimum key length for Diffie-Hellman   For JDK 8 and earlier, edit lib/security/java.security and add the desired length to the jdk.tls.disabledAlgorithms property by appending DH KeySize < min keylength   In JDK 9, java.security has been moved to conf/security/java.security For example, if the current value is: jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768 and one wanted to increase the minimum key length to 1024 the new value would be: jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 1024 If no value is set for DSA keySize, just append it at the end of the property after a comma.  

General Reference articles

Roadmap & Changelog for Oracle JRE/JDK https://www.java.com/en/jre-jdk-cryptoroadmap.html

Debugging SSL/TLS Connections: https://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/ReadDebug.html

How-to configuration guide - Oracle's JDK and JRE Cryptographic Algorithms https://www.java.com/en/configure_crypto.html

⚠️ **GitHub.com Fallback** ⚠️