SQL Server JDBC Error on Java 8: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption
I turned on SSL logging in the Java 8 JVM on a Linux instance which reproduces the problem. SSL logging is turned on using -Djavax.net.debug=ssl:handshake:verbose
. This revealed some useful information.
The workaround that we are using in production and has proven to work for us is to set this parameter on the JVM:
-Djdk.tls.client.protocols=TLSv1
If you want more details, please read on.
On a server where the problem can be reproduced (again, only 5-10% of the time), I observed the following:
*** ClientHello, TLSv1.2
--- 8<-- SNIP -----
main, WRITE: TLSv1.2 Handshake, length = 195
main, READ: TLSv1.2 Handshake, length = 1130
*** ServerHello, TLSv1.2
--- 8<-- SNIP -----
%% Initialized: [Session-79, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256]
** TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
--- 8<-- SNIP -----
Algorithm: [SHA1withRSA]
--- 8<-- SNIP -----
*** Diffie-Hellman ServerKeyExchange
--- 8<-- SNIP -----
*** ServerHelloDone
*** ClientKeyExchange, DH
--- 8<-- SNIP -----
main, WRITE: TLSv1.2 Handshake, length = 133
--- 8<-- SNIP -----
main, WRITE: TLSv1.2 Change Cipher Spec, length = 1
*** Finished
verify_data: { 108, 116, 29, 115, 13, 26, 154, 198, 17, 125, 114, 166 }
***
main, WRITE: TLSv1.2 Handshake, length = 40
main, called close()
main, called closeInternal(true)
main, SEND TLSv1.2 ALERT: warning, description = close_notify
main, WRITE: TLSv1.2 Alert, length = 26
main, called closeSocket(true)
main, waiting for close_notify or alert: state 5
main, received EOFException: ignored
main, called closeInternal(false)
main, close invoked again; state = 5
main, handling exception: java.io.IOException: SQL Server returned an incomplete response. The connection has been closed. ClientConnectionId:12a722b3-d61d-4ce4-8319-af049a0a4415
Notice that TLSv1.2 is selected by the database server and used in this exchange. I've observed that, when connections fail from the problematic linux service, TLSv1.2 is ALWAYS the level which was selected. However, connections do not ALWAYS fail when TLSv1.2 is used. They only fail 5-10% of the time.
Now here is an exchange from a server that does NOT have the problem. Everything else is equal. I.e., connecting to the same database, same version of the JVM (Java 1.8.0_60), same JDBC driver, etc. Notice that, here, TLSv1 is selected by the database server instead of TLSv1.2 as in the faulty server's case.
*** ClientHello, TLSv1.2
--- 8<-- SNIP -----
main, WRITE: TLSv1.2 Handshake, length = 207
main, READ: TLSv1 Handshake, length = 604
*** ServerHello, TLSv1
--- 8<-- SNIP -----
Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA
--- 8<-- SNIP -----
%% Initialized: [Session-79, TLS_RSA_WITH_AES_128_CBC_SHA]
** TLS_RSA_WITH_AES_128_CBC_SHA
--- 8<-- SNIP -----
Algorithm: [SHA1withRSA]
--- 8<-- SNIP -----
***
*** ServerHelloDone
*** ClientKeyExchange, RSA PreMasterSecret, TLSv1
--- 8<-- SNIP -----
main, WRITE: TLSv1 Handshake, length = 134
main, WRITE: TLSv1 Change Cipher Spec, length = 1
*** Finished
verify_data: { 26, 155, 166, 89, 229, 193, 126, 39, 103, 206, 126, 21 }
***
main, WRITE: TLSv1 Handshake, length = 48
main, READ: TLSv1 Change Cipher Spec, length = 1
main, READ: TLSv1 Handshake, length = 48
*** Finished
So, when TLSv1 is negotiated between the Linux JVM and the SQL Server, connections are ALWAYS successful. When TLSv1.2 is negotiated, we get sporadic connection failures.
(Note: Java 7 (1.7.0_51) always negotiates TLSv1, which is why the problem never occurred for us with a Java 7 JVM.)
The open questions we still have are:
- WHY is that the same Java 8 JVM run from 2 different Linux servers will always negotiate TLSv1, but when connecting from another Linux server it always negotiates TLSv1.2.
- And also why are TLSv1.2 negotiated connections successful most, but not all, of the time on that server?
Update 6/10/2017:
This posting from Microsoft describes the problem and their proposed solution.
Resources:
http://www.infoworld.com/article/2849292/operating-systems/more-patch-problems-reported-with-the-ms14-066-kb-2992611-winshock-mess.html
http://www.infoworld.com/article/2849292/operating-systems/more-patch-problems-reported-with-the-ms14-066-kb-2992611-winshock-mess.html
http://blogs.msdn.com/b/jdbcteam/archive/2008/09/09/the-driver-could-not-establish-a-secure-connection-to-sql-server-by-using-secure-sockets-layer-ssl-encryption.aspx
Java 8 , JCE Unlimited Strength Policy and SSL Handshake over TLS
http://blogs.msdn.com/b/saponsqlserver/archive/2013/05/10/analyzing-jdbc-connection-issues.aspx
https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#descPhase2
https://blogs.oracle.com/java-platform-group/entry/java_8_will_use_tls
The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: Unexpected rethrowing
add this property to application entry point
Security.setProperty("jdk.tls.disabledAlgorithms","SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024,EC keySize < 224, 3DES_EDE_CBC, anon, NULL");
if you use spring boot
you can use like this
import java.security.Security;
public class Application {
public static void main(String[] args) {
Security.setProperty("jdk.tls.disabledAlgorithms","SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024,EC keySize < 224, 3DES_EDE_CBC, anon, NULL");
SpringApplication.run(Application.class, args);
}
}
The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption in liquibase
That version is too old to support TLS 1.2. If your client won't support older cypher suites, and you need to use an encrypted connection, then you'll need to patch the SQL Server to support TLS 1.2.
In your case you would apply Service Pack 3 and then ths update SQL Server 2008 R2 SP3 – KB4057113.
As outlined here: KB3135244 - TLS 1.2 support for Microsoft SQL Server
SQL Server JDBC Error: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption
Ok, so we worked with Microsoft Support on this issue and this is the understanding that we came to.
Microsoft added/enabled TLS 1.0 and TLS 1.1 to the Database Server for testing purposes only since Microsoft does not support TLS 1.0 anymore. This lowered the security protocol to a lower state but were able to establish SQL Connectivity between the Application server and the Database Server, but still the Application initially couldn't connect. Microsoft thinks that it is because of the current connection provider/driver that is being used by the application and they wouldn't support that part of it since that is Java/Oracle's JDBC driver.
In our case, the application did connect after enabling the TLS 1.0 and TLS 1.1 after sometime.
This may or may not work in your case.
So the recommended solutions if you have the resources to modify the application, are to update the drivers for the application, test and redeploy.
If you don't have the resources to the application then the options are these:
1.Rollback to older Servers for SQL Server. This could work but there is no guarantee.
Also another thing to note is that SQL Server 2008 and 2008R2 are out of support, so the oldest we could go (and still stay supported) would be SQL Server 2012 which may not resolve the issue.
2.Open the security wide open. This will very likely solve the issue, but is most definitely not recommended. It is likely that the issue has to do with extremely outdated security providers, that are no longer supported. So, opening your security wide open will likely resolve the issue, but this is not recommended.
3.Rewrite the application which is not the easiest option, but is the only one that is fully recommended by Microsoft.
See this https://serverfault.com/questions/649052/do-i-have-to-enable-tls-1-0-in-windows-2008-r2 and this https://www.youtube.com/watch?v=vUuR_M3biDU if you'd like to enable TLS by yourself. The server will require reboot after you make this change.
Cannot connect to SQL Server server with MS JDBC Driver from CentOS 8 server: SSL error but not using secure connection
So, the way I was able to get this to work after much trial and error was to copy the java.security file from the windows 10 install to the CentOS 8 install. The ONLY thing I can see as different between the two was in this section:
'# List of comma-separated packages that start with or equal this string
'# will cause a security exception to be thrown when
'# passed to checkPackageDefinition unless the
'# corresponding RuntimePermission ("defineClassInPackage."+package) has
'# been granted.
'#
'# by default, none of the class loaders supplied with the JDK call
'# checkPackageDefinition.
'#
The entries in CentOS included at the end of the list:
org.GNOME.Accessibility.,\
org.GNOME.Bonobo.
The entries in the Windows version had only one entry at the end:
com.sun.java.accessibility.
That was the only difference I could find. And, I don't understand why that made a difference.. But it DOES connect without error now and that is all I wanted....
The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. How to solve this error?
So the reason why my IDE works and jar doesn't is because jar was running on new JRE version. After i run it with older it was working fine.
driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption
I don't know why but when running debug on the line where I connect to debug gave me this error. This occurred to me in automation tool Katalon (which uses groovy)
(Of course b/c it was not working I was trying to use debug exactly there)
Related Topics
File Exists and Is Directory, But Listfiles() Returns Null
Portrait for Phone, Landscape for Tablet (Android-Layout)
How to Create Button Dynamically in Android
How to Launch Home Screen Programmatically in Android
What Is the Use of Basecolumns in Android
Android Call a Method from Another Class
Parcelable and Inheritance in Android
Android Studio - Failed to Find Target Android-18
Onrequestpermissionsresult Not Being Called in Dialog Fragment
Kotlin-Android: Unresolved Reference Databinding
Android Color Notification Icon
How to Remove Only Trailing Spaces of a String in Java and Keep Leading Spaces
Android Httpclient Persistent Cookies
How to Include the Spongy Castle Jar in Android
Using Httpclient and Httppost in Android with Post Parameters