Brief Introduction to SSL
The Oracle database product supports SSL/TLS connections in its standard edition (since 12c). The Secure Sockets Layer (SSL) protocol provides network-level authentication, data encryption, and data integrity. When a network connection over SSL is initiated, the client and server perform a handshake that includes:
• Negotiating a cipher suite for encryption, data integrity, and authentication
• Authenticating the client by validating its certificate
• Authenticating the server by verifying that it’s Distinguished Name (DN) is expected
• Client and server exchange key information using public key cryptography.
To establish an SSL connection the Oracle database sends its certificate, which is stored in a wallet. Therefore, on the server the configuration requires a wallet and on the client, the JDBC thin driver can use different formats to store the client’s certificate and key: JKS, Wallet or PKCS12.
In this blog, we will provide clear steps to establish an SSL connection over TLSv1.2 using the JDBC thin driver with either JKS files or a wallet.
Note: One of the Oracle Cloud offerings, Exadata Express Cloud Service (EECS) mandates TLSv1.2.
SSL Connection using TLSv1.2
SSL Connection using JKS
SSL Connection using Oracle Wallets
SSL connection using TLSv1.2
JDK 7 and JDK 8 releases support TLSv1.2 protocol. The other protocols such as TLSv1.1, TLSv1, SSLv3, and SSLv2 have security vulnerabilities and the recommendation is to use the latest standard version TLSv1.2 and use more secure SSL cipher suites. Follow these pre-requisites below to use TLSv1.2.
1: Make sure you have the correct JDBC Thin driver
If you are using ojdbc8.jar from 12.2.0.1 version then, you are all set. But, if you are using 12.1.0.2 JDBC driver then you need to either download the 12.1.0.2 patched driver or apply the patch for the bug 19030178 that allows TLSv1.2. Note that the patch allows TLSv1.2 but doesn't enable it by default. So, you must set the property oracle.net.ssl_version=1.2. This property can be set either as a system property (using -D) or through the datasource properties.
2: JDK version and JCE files
If you are NOT using JDK9 or JDK8u162 then download the JCE Unlimited Strength Jurisdiction Policy Files. Refer to README for installation notes. Without the Java Cryptography Extension (JCE) files, the strong cipher suites (for example TLS_RSA_WITH_AES_256_CBC_SHA256) won't be enabled.
P.S: If you are using JDK7 and using a strong cipher suite such as TLS_RSA_WITH_AES_256_CBC_SHA256, then you must enable it through the property
-Doracle.net.ssl_cipher_suites="(TLS_RSA_WITH_AES_256_CBC_SHA256)"3: Set the Database Connection String
-
Download DataSourceSample.java or UCPSample.java from Github
-
Modify the Java code to include the correct DB_URL, DB_USER, and DB_PASSWORD of the database that you have access to.
Make sure to use TCPS protocol with its corresponding port and configure the server's DN for mutual authentication.
Example: DB_USER = "hr", DB_PASSWORD ="hr", and
DB_URL = "jdbc:oracle:thin:@(DESCRIPTION= (ADDRESS=
(PROTOCOL=TCPS)(PORT=1522)(HOST=myhost))
(CONNECT_DATA=(SERVICE_NAME=myorcldbservicename))
(SECURITY=(ssl_server_cert_dn="CN=testcert.oracle.com, O=Oracle Corporation,L=Redwood City,ST=California,C=US")))"
Note: If you are using tnsnames.ora then it is sufficient to use TNS alias in the URL E.g., DB_URL="jdbc:oracle:thin:@dbaccess". Set the path of tnsnames.ora with oracle.net.tns_admin system property.
SSL connection using TLSv1.2 with JKS
Java Key Store (JKS) is used as a container for the client's certificates exchanged between the server and the client. The advantage of using JKS is its native support in the JRE and there is no need of any additional security provider because Sun's default PKI provider supports JKS format. Refer to the definitions of trustStore and keyStore for clarity.
trustStore stores certificates from trusted Certificate Authorities (CA) which will be used to verify a certificate presented by the server in the SSL connection.
keyStore contains the client certificate which will be used for authentication and it also contains a set of private/public keys that will be used for encryption. Applications should present the keyStore when the client needs to be authenticated on the server.
Follow these steps to connect to Oracle DB using JDBC Thin driver and JKS:
Step 1: Complete the pre-requisites 1-3 from the "SSL Connection using TLSv1.2" section
Step 2: Use the JKS (keyStore.jks and trustStore.jks) files
Make sure to have the files keyStore.jks and trustStore.jks at a location accessible to the application and use the connection properties to provide the JKS file location and password. Refer to the sample commands for the properties.
Step 3: Enable the server DN matching
Server DN matching is used for mutual authentication during the SSL handshake. Set this using oracle.net.ssl_server_dn_match=true system property.
Step 4: Sample commands to run a Java program using JKS files
=== JDK8 AND THE 12.2.0.1 JDBC THIN DRIVER ====java -Doracle.net.ssl_server_dn_match="true" -Doracle.net.tns_admin=./lib -Djavax.net.ssl.trustStore="truststore.jks" -Djavax.net.ssl.trustStorePassword="welcome1" -Djavax.net.ssl.trustStoreType="JKS" -Djavax.net.ssl.keyStore="/client_credentials/keystore.jks" -Djavax.net.ssl.keyStoreType="JKS" -Djavax.net.ssl.keyStorePassword="welcome1" DataSourceSample==== JDK7 AND THE 12.1.0.2 PATCHED THIN DRIVER ====
java -Doracle.net.ssl_version="1.2" -Doracle.net.tns_admin=./lib -Doracle.net.ssl_server_dn_match="true" -Doracle.net.ssl_cipher_suites="(TLS_RSA_WITH_AES_256_CBC_SHA256)" -Djavax.net.ssl.trustStore="/client_credentials/truststore.jks" -Djavax.net.ssl.trustStorePassword="welcome1" -Djavax.net.ssl.keyStore="/client_credentials/keystore.jks" -Djavax.net.ssl.keyStorePassword="welcome1" DataSourceSample
SSL connection using TLSv1.2 with Oracle Wallets
Wallets created by Oracle Wallet Manager or "orapki" use the standard PKCS12 format to store X.509 certificates and private keys. The wallet is stored in a file named "ewallet.p12". If you enable auto-login in the wallet, an obfuscated copy of the wallet is created in the file "cwallet.sso" which can then be used without providing the password. Note that you must use Oracle’s PKI provider named “OraclePKI” to access Oracle wallets from Java.
Follow these steps to connect to Oracle DB using JDBC Thin driver and Oracle Wallets:
Step 1: Complete the pre-requisites 1-3 from the "SSL Connection using TLSv1.2" section
Step 2: Add the required dependant jars for using Oracle Wallets
Along with JDBC thin driver (e.g., ojdbc8.jar from 12.2.0.1), also download oraclepki.jar, osdt_cert.jar, and osdt_core.jar files (these are available under $ORACLE_HOME/lib) or you can also download these from JDBC Download page on OTN and place them in the CLASSPATH.
Step 3: Enable Oracle PKI provider
Follow any of the two ways to enable Oracle PKI provider.
(a) Enable it statically as follows:
If you use SSO wallets (cwallet.sso), Add the OraclePKIProvider at the end of the provider list in the file java.security (this file is part of your JRE install located at $JRE_HOME/jre/lib/security/java.security) which typically looks like:
security.provider.1=sun.security.provider.Sun security.provider.2=sun.security.rsa.SunRsaSign security.provider.3=com.sun.net.ssl.internal.ssl.Provider security.provider.4=com.sun.crypto.provider.SunJCE security.provider.5=sun.security.jgss.SunProvider security.provider.6=com.sun.security.sasl.Provider security.provider.7=oracle.security.pki.OraclePKIProvider
Note that if another provider supports the type “SSO”, then it should be inserted after Oracle’s PKI provider.
If you use PKCS12 wallets (ewallet.p12), move Oracle’s PKI provider to position #3 or any position ahead of Sun’s provider which also supports PKCS12 but which is not compatible with Oracle’s wallets. So the list of providers in java.security look like:
security.provider.1=sun.security.provider.Sun security.provider.2=sun.security.rsa.SunRsaSign security.provider.3=oracle.security.pki.OraclePKIProvider security.provider.4=com.sun.net.ssl.internal.ssl.Provider security.provider.5=com.sun.crypto.provider.SunJCE security.provider.6=sun.security.jgss.SunProvider security.provider.7=com.sun.security.sasl.Provider
(b) Enable it dynamically in your Java program as follows:
If you use SSO wallets, you simply need to “add” Oracle’s PKI provider because
the order does not matter (assuming that there is no other provider for SSO):
Security.addProvider(new oracle.security.pki.OraclePKIProvider());If you use PKCS12 wallets, Oracle PKI’s provider needs to be inserted at position#3:
Security.insertProviderAt(new oracle.security.pki.OraclePKIProvider(),3);
Step 4: Set the Oracle Wallet location
Set the wallet location using oracle.net.wallet_location="(SOURCE=(METHOD=file)(METHOD_DATA=(DIRECTORY=/home/test/cloud)))
The wallet location is where the SSO wallets (cwallet.sso and ewallet.p12) are placed.
Step 5: Enable the server DN matching
Server DN matching is used for mutual authentication during the SSL handshake. Set this using oracle.net.ssl_server_dn_match=true system property.
Step 6: Sample commands to run a Java program using Oracle Wallets
If you are using a plain Java program then use the command as shown below to connect using Oracle Wallets and JDBC driver.
java -classpath ./lib/ojdbc8.jar:./lib/oraclepki.jar:./lib/osdt_cert.jar:./lib/osdt_core.jar:. -Doracle.net.tns_admin=./lib -Doracle.net.wallet_location="(SOURCE=(METHOD=file)(METHOD_DATA=(DIRECTORY=/home/test/cloud/lib)))" -Doracle.net.ssl_server_dn_match=true DataSourceSample
Appendix:
If you run into more issues, you can turn on tracing using -Djavax.net.debug=all
Refer to the JDBC Troubleshooting Tips
Refer to Java Connectivity with ATP/ADW using 19c and 18c for the latest drivers.
Refer to the Appendix section of SSL with Oracle JDBC driver for information about creating the truststores and keystores