As enterprise applications increasingly rely on cloud and distributed architectures, secure communication between clients and databases has become essential. The Oracle AI Database contains sensitive personal information (employee and financial records, customer orders, transactions, product information, etc.), and it is important to safeguard this data against security threats such as eavesdropping, data theft, data tampering, network-based threats, and the falsification of user identities.

Data encryption and data integrity can be achieved by configuring either Oracle Net native encryption (NNE) (for example, AES and SHA2 at the Oracle Net layer) or Transport Layer Security (TLS) or Secure Socket Layer (SSL). TLS encryption protects sensitive data in transit, prevents eavesdropping, and ensures data integrity between client applications and the Oracle database servers. By leveraging TLS with the Oracle JDBC Thin driver, organizations can ensure that application-to-database connections meet compliance standards and enterprise security best practices.

This blog provides a comprehensive overview of TLS support in the Oracle JDBC Thin driver, including use cases, sample code, implementation best practices, and troubleshooting tips. Please note that Secure Socket Layer (SSL) and Transport Layer Security (TLS) are used interchangeably. Refer to section 9.7 Support for TLS of the JDBC Developer’s Guide for detailed TLS features.

1. Benefits of TLS

Secure Sockets Layer (SSL) and Transport Layer Security (TLS) are industry-standard protocols for securing network connections. TLS uses RSA public-key cryptography in conjunction with symmetric-key cryptography to provide authentication, encryption, and data integrity. The TLS benefits are listed below.

  • Data Encryption: Encrypts all the data transmitted between client and server using a public and private key pair. 
  • Authentication: TLS uses digital certificates conforming to the X.509v3 standard for authentication. It is accomplished through a Certificate Authority (CA), a third party trusted by both communication parties.
    • One-way TLS (Server Authentication): The database server presents a certificate that the Oracle JDBC Thin driver must validate. 
    • Two-way TLS (mTLS; mutual authentication or Client & Server authentication): Both the database and the client present certificates that must be validated by both sides. 
  • Data Integrity: Ensures that the messages exchanged between the client and the database are not tampered with. It uses secret-key cryptography and digital signatures to ensure data privacy and integrity. 
  • Compliance: Organizations mandate encryption of data in transit to meet the regulatory and audit requirements. This can be met using TLS connections. 

TLS is supported in all the latest Oracle JDBC Thin drivers, i.e., 26ai, 23ai, 19c, and 21c. Refer to the JDBC Driver Download Page to download specific versions. 

2. TLS Settings on Server Side and Client Side 

TLS-specific settings must be configured on both the server and client sides to establish a secure, encrypted connection. The section below shows how the TLS settings look on each side.

2.1 Enable TLS on the server side:

2.1.1 Connection URL with TCPS
The listener (listerner.ora) must be configured to use the TCPS protocol. Also, the port must be the TCPS port.
LISTENER = (ADDRESS_LIST=
(ADDRESS=(PROTOCOL=tcps)(HOST=servername)(PORT=2484)))


2.1.2 Specify the Wallet Location
The server’s auto-login wallet location must be provided in both sqlnet.ora and listener.ora. In most cases, both files share the same wallet location, but this is not always the case; the listener could use its own wallet. For simplicity, let us assume that both sqlnet.ora and listener.ora use the same wallet location.

WALLET_LOCATION=(SOURCE=(METHOD=FILE)(METHOD_DATA=(DIRECTORY=/server/wa
llet/path/)))

2.1.3. Set the SSL Client Authentication
The property SSL_CLIENT_AUTHENTICATION should be set to TRUE or FALSE in the server setting files, sqlnet.ora and listener.ora. The default value is TRUE, indicating that mutual authentication is enabled. When SSL_CLIENT_AUTHENTICATION=TRUE, the JDBC Thin driver must be configured to send the client’s digital certificate, which must be accepted by the Oracle AI Database server; otherwise, the connection will fail. It can be set to FALSE to indicate one-way TLS.

SSL_CLIENT_AUTHENTICATION= FALSE –> for one-way TLS. 
SSL_CLIENT_AUTHENTICATION= TRUE –> for two-way TLS or mutual authentication or mTLS

2.2 Enable TLS on the client side:

2.2.1 Connection URL with TCPS and hostname matching enabled
The connection string should use the TCPS protocol to enable TLS with the Oracle JDBC Thin Driver. Enabling the hostname matching is recommended to provide additional validation and help prevent potential attacks. The hostname matching is enabled by setting ssl_server_dn_match=yes.

When using the Easy Connection URL, hostname matching is enabled by default. However, with the long-form connection string, ssl_server_dn_match=yes must be explicitly set.

// Easy Connection URL with host name matching enabled by default
jdbc:oracle:thin:@tcps://myhost:1522/myorcldbservicename

// Long form Connection URL with host name matching enabled
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=myhost)(PORT=1522)(CONNECT_DATA=(SERVICE_NAME=myorcldbservicename)(security=(ssl_server_dn_match=yes))) 

2.3 TLS-related Connection Properties:

The following TLS-related properties are required based on the functionality that you want to use. These properties can be set as name-value pairs in the Easy Connection URL, set as connection properties programmatically, or as system properties. You can refer to the complete list of TLS connection properties in the JDBC Javadoc

Some of the important connection properties are listed below:

  • oracle.net.wallet_location and oracle.net.wallet_password: When using Oracle Wallets, use this property to specify the location of the wallet. If you do not provide wallet_password, then Oracle SSO wallet (cwallet.sso) is used; otherwise, PKCS12 wallet (ewallet.p12) or PEM (ewallet.pem) will be used. 
  • javax.net.ssl.trustStore, javax.net.ssl.trustStoreType, and javax.net.ssl.trustStorePassword:  If you are enabling one-way TLS, then use these properties to specify the path of the trusted certificate. A truststore is used to verify that the certificate coming from the server is trusted.  Note that the trustStoreType can be SSO, PKCS12, PEM, or JKS, depending on the certificate used.
  • javax.net.ssl.keyStore, javax.net.ssl.keyStoreType, and javax.net.ssl.keyStorePassword: If the client authentication or the mutual authentication is enabled, then “keyStore” contains the client certificate required for authentication. Note that the keyStoreType can be SSO, PKCS12, PEM, or JKS, depending on the certificate used for the client authentication.

These are other TLS-related properties, listed here for reference.

  • oracle.net.ssl_server_dn_match=true: Used to force the driver to verify that the server’s Distinguished Name (DN) matches. It is enabled by default when using the easy connect URL but, needs to be explicitly set with long form connection URL. It can be set as part of the connection string using (security=(ssl_server_dn_match=yes).
  • oracle.net.ssl_certificate_alias: Used to specify the keystore certificate alias. 
  • oracle.net.ssl_certificate_thumbprint: When a keystore (either wallet or JKS file) contains multiple certificates, this property can be used to specify the thumbprint of the certificate to be used by the driver during the client authentication part of the SSL handshake. This can also be configured via the connection URL using the SECURITY parameter SSL_CERTIFICATE_THUMBPRINT or using the connection property CONNECTION_PROPERTY_THIN_SSL_CERTIFICATE_THUMBPRINT
  • oracle.net.ssl_pem_private_key_index: Used to specify which private key to use in a PEM file. By default, the driver will use the first private key it finds, unless a different index is specified in this connection property.
  • oracle.net.authentication_services: Activate TLS as an authentication service in the database. Note that this property can be used to enable any other authentication services, such as Kerberos, RADIUS, BEQ, or TCPS. 
  • oracle.net.ssl_version or CONNECTION_PROPERTY_THIN_SSL_VERSION: Restricts the TLS version that can be used. feature. Do not configure the protocol version; let the JDK choose the most secure version. Refer to Section 9.7.4 on setting TLS v1.3 of the JDBC Developer’s Guide for more details. 
  • oracle.net.ssl_cipher_suites: Enable a subset of cipher suites or force the SSL handshake to use only these defined cipher suites. Refer to the cipher suites supported in JDK21. Also, the driver supports all cipher suites supported in the database. Refer to the DB-supported cipher suites in 23ai. The recommendation is not to configure cipher suites, as the best cipher suite will be negotiated automatically between server and client.

3. Keystores and Truststores

In TLS connections, file-based keystores and truststores are used to store security certificates in Java environments and many enterprise applications. These files serve different purposes but complementary roles.

Keystore
A keystore is a file that stores private keys and the corresponding public certificates for a server or client. It is used to verify your identity to others. This is typically used on the server side, or on clients for mutual Authentication or mTLS. Example: A web server’s keystore stores its private key and SSL certificate, enabling it to prove its identity to browsers.

Truststore
Truststore is a file with a similar format to a keystore that stores trusted third-party certificates, such as certificates from Certificate Authorities or public certificates. It is used to verify the identity of another party (server or client) and to determine which certificates are considered valid. Example: A client’s truststore contains CA certificates, so it can verify that a server’s certificate is legitimate.

LabelKeystoreTruststore
ContainsPrivate keys + certificatesOnly trusted public certificates (CAs)
Used for Authentication (prove identity)
(e.g., server or client authentication)
Trust validation (verify identity)
(eg, server’s identity in HTTPS)
Who Uses ItServers (presenting identity)Clients (validating identity)

In mutual TLS (mTLS):
Server side: Uses both – keystore for its own identity, truststore to verify client certificates
Client side: Uses both – keystore to prove its identity to the server, truststore to verify the server

In summary, the keystore is your ID and credentials, while the truststore is the list of authorities you trust to verify others’ IDs.

Recommendation:

Case 1: If both truststore and keystore are stored in the same file (cwallet.sso or ewallet.p12 or ewallet.pem), then use wallet location connection properties.
oracle.net.wallet_location and oracle.net.wallet_password

Case 2: If both truststore and keystore are stored in different files, then use keystore and truststore connection properties.
javax.net.ssl.trustStore, javax.net.ssl.trustStoreType, and javax.net.ssl.trustStorePassword,
javax.net.ssl.keyStore, javax.net.ssl.keyStoreType, and javax.net.ssl.keyStorePassword

Case 3: If multiple keys are in the keystore, then use the thumbprint, alias, or index to choose the keystore to use for establishing the connections.
oracle.net.ssl_certificate_thumbprint or oracle.net.ssl_certificate_alias or oracle.net.ssl_pem_private_key_index

4. Choosing the Wallet

Oracle SSO Wallet (cwallet.sso)
A wallet is a password-protected container for storing authentication and signing credentials, including private keys, certificates, and trusted certificates required by SSL. While using Auto-login Oracle SSO wallets (cwallet.sso), you don’t need to provide the password because SSO (Single Sign-On) Wallets provide a capability that allows users to access multiple Oracle services without repeatedly entering credentials. The wallet securely stores user credentials, enabling seamless authentication. Make sure “auto-login” is enabled when creating the “truststore” wallet using the Oracle Wallet Manager (orapki tool). The clients need to provide only the path to the Oracle SSO wallet.

The Oracle JDBC driver has been enhanced to automatically load the provider, so there is no need to add the provider.  For example, the thin JDBC driver loads the Oracle PKI provider when the class path has oraclepki.jar or when the oracle.net.wallet_location connection property is present. Refer to section 9.7.5.1 Provider Resolution for more information.

PKCS12 (ewallet.p12)
PKCS12 (.p12 or .pfx) is a standard format for storing cryptographic keys and certificates in a single, portable, password-protected file. It is recommended to use PKCS12 instead of JKS. Java’s “key tool” can be used to read and write PKCS12 files.

PEM (ewallet.pem)
PEM (Privacy Enhanced Mail) is a base64-encoded format (with —–BEGIN … —–and ——END ….—— delimiters) for storing SSL/TLS certificates and keys. It is widely used in the open-source community (OpenSSL, Apache HTTP Server, Nginx).

JKS (truststore.jks and keystore.jks)
JKS (Java KeyStore) is the original proprietary format for Java keystores, frequently used by Java applications to enable SSL (for both servers and clients). JKS is less portable and less interoperable than PKCS12. Therefore, Java is moving towards PKCS12 as the default keystore format. When “key tool” is used to create a JKS keystore, you will see the following warning.

The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12, which is an industry standard format using “keytool -importkeystore -srckeystore ./client_jks/client.jks -destkeystore ./client_jks/client.jks -deststoretype pkcs12”.

5. Prerequisites

(1) Make sure to use the latest Oracle JDBC driver based on the JDK version that you are using. Download the Oracle JDBC driver and other libraries from the JDBC Download page or from the Central Maven repository. The ojdbcX-full.tar.zip contains the Oracle JDBC driver along with all other additional libraries. Similarly, ojdbc17-production, ojdbc11-productionand ojdbc8-production pull all libraries for Maven users. 

  • You must use oraclepki.jar to access Oracle Wallets from Java.
    • For 26ai and 23ai clients: only oraclepki.jar is required in the classpath.
    • Older versions, 21c or 19c: oraclepki.jar, osdt_core.jar, and osdt_cert.jar are required in the classpath.
  • If you are using JKS, then you don’t need any additional libraries. Make sure that you are using the latest JDK version. If you are using the older versions then it should be atleast JDK 8(u163+) or higher.

(2) Download the corresponding code samples ADBQuickStart.java for ADB database or OneTLS-Test.java or MutualTLS-Test.java from GitHub.
(3) Make sure the database connection URL has TCPS as the protocol, and hostname match verification is set to yes.

// Long form Connection String with more readable connection descriptors
DB_URL = "jdbc:oracle:thin:@(description= (retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1522)(host= myhost))(connect_data=(service_name= myorcldbservicename))(security=(ssl_server_dn_match=yes)))"

// Easy Connection URL
DB_URL = “jdbc:oracle:thin:@tcps://myhost:1522/myorcldbservicename

6. One Way TLS : TLS for Encryption and Server Authentication

If the server has a certificate issued by a well-known trusted authority, there is no need to configure “trustsore” because the Java runtime already includes such authorities. In some cases, you will need a “truststore,” for example, when you use a self-signed certificate. Setting a custom truststore lets you override the trusted authorities listed. The “Truststore” contains trusted CA certificates and public certificates from others. This is used to verify someone else’s identity. The “trustsore” is used to validate the server’s certificate. Any “truststore” format can be used, as long as a provider is specified for that format.

Make sure that on the server side, one-way TLS is enabled, which means client authentication is turned off by setting SSL_CLIENT_AUTHENTICATION = FALSE in both sqlnet.ora and listener.ora.

6.1 TLS with Autonomous AI Database (ADB)

Oracle Autonomous AI Database uses publicly trusted certificates from standard, well-known Certificate Authorities (CAs). Modern Oracle Cloud (OCI) endpoints use certificates signed by these CAs, which are pre-installed in the system/Java truststore on the modern PCs and servers. The Oracle JDBC client verifies the identity of the database server using the built-in truststore. This eliminates the need to download wallets to establish connections.

Note that, since it is an Autonomous Database, server-side settings are configured during database creation.

Follow these steps:
Step 1: Ensure the prerequisites are met. 
Step 2: Download the ADBQuickStart.java and update the connection URL.
You don’t need to download the wallets. Copy the TLS URL from the OCI console by navigating to your Autonomous AI Database Details page and clicking on Database Connection. Under TLS Authentication, select TLS to copy the connection string for the database. The connection string looks like the one below.

DB_URL = "jdbc:oracle:thin:@(description=(retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1521)(host=adb.us-phoenix-1.oraclecloud.com))(connect_data(service_name=testservice_jdbctestdb_high.adb.oraclecloud.com))(security=(ssl_server_dn_match=yes)))

6.2 TLS with On-premise Database

For TLS with the on-premises database, you can use any format of “truststore” as long as the provider for the same is available. Oracle SSO, PKCS12, PEM, or JKS truststores can be used to validate the server’s certificate.

Follow these steps for SSO, PKCS12, PEM, or JKS as the truststore

Step 1: Ensure the prerequisites are met. 
Step 2: Download the TBD and update the connection URL to point to your database.
Step 3: Ensure the corresponding truststore/wallets are located at a location accessible to the application, and remember the password for PKCS12, PEM, or JKS. Oracle SSO Wallets do not need a password if created using “auto-login” enabled. Note that only one type of certificate is required for establishing the connection.
Step 4: If using PKCS12 files, please add the following line of code to update the provider. The ewallet.p12 created using the orapki tool has a different format than the one in the standard ewallet.p12 created using the keytool. In scenarios when the orapki tool is used to create PKCS12 files, you must update the provider to use OraclePKIProvider using the below line of code.

Security.insertProviderAt(new oracle.security.pki.OraclePKIProvider(), 1);

Step 5: Set the trustStore related conection properties as shown below. Note that you must select only one type of truststore.

// For Oracle SSO Wallets 
props.setProperty("javax.net.ssl.trustStore","D:\\truststore\\cwallet.sso");
props.setProperty("javax.net.ssl.trustStoreType", "SSO"); 

// For PKCS12 Wallets 
props.setProperty("javax.net.ssl.trustStore","D:\\truststore\\ewallet.p12");
props.setProperty("javax.net.ssl.trustStoreType", "PKCS12"); 
props.setProperty("javax.net.ssl.trustStorePassword","welcome123");

// For PEM files 
props.setProperty("javax.net.ssl.trustStore","D:\\truststore\\ewallet.pem");
props.setProperty("javax.net.ssl.trustStoreType", "PEM"); 
props.setProperty("javax.net.ssl.trustStorePassword","welcome123");

// For JKS files
props.setProperty("javax.net.ssl.trustStore","D:\\truststore\\truststore.jks");
props.setProperty("javax.net.ssl.trustStoreType", "JKS"); 
props.setProperty("javax.net.ssl.trustStorePassword","welcome123");

Alternatively, you can use these properties to set it in the application code. 
props.put(OracleConnection.CONNECTION_PROPERTY_THIN_JAVAX_NET_SSL_TRUSTSTORE,"/home/user/cloud/ewallet.p12"); 
props.put(OracleConnection.CONNECTION_PROPERTY_THIN_JAVAX_NET_SSL_TRUSTSTORETYPE,"PKCS12"); 
props.put(OracleConnection.CONNECTION_PROPERTY_THIN_JAVAX_NET_SSL_TRUSTSTOREPASSWORD,"Welcome123");

7. Mutual Authentication: TLS for Encryption and Client and Server Authentication (mTLS)

The “truststore” must be specified as indicated in Case 1 above, which handles server authentication. For mutual authentication, the client needs to be authenticated on the server. Therefore, “keystore” is specified. The “keystore” contains not only the client certificate, which will be used for authentication, but also a set of private and public keys used for encryption. Any format of “keystore” can be used as long as a provider is specified for that format.

For enabling Mutual Authentication, client authentication must be turned on using the parameter,  SSL_CLIENT_AUTHENTICATION =TRUE on the server side as well as on the listener (sqlnet.ora and listener.ora). 

7.1 mTLS with Autonomous AI Database

Oracle Autonomous AI Database’s server authentication is handled as explained in Case 1. For mutual authentication (mTLS), the required client certificate is included in the downloadable wallet. Since client certificates are present in the wallet and server authentication is addressed, we recommend using the connection properties oracle.net.wallet_location and oracle.net.wallet_password for simplicity.

Follow these steps for SSO, PKCS12, PEM, or JKS as the keystore

Step 1: Ensure the prerequisites are met. 
Step 2: Download the client-credentials ZIP file. From the OCI Console, navigate to your Autonomous AI Database details page and click on Database Connection. Under Download client Credentials (Wallet), choose Instance Wallet and click on Download Wallet. Save the wallets to an accessible location. The client-credentials zip contains SSO, PEM, PKCS12, JKS, ojdbc.properties, and tnsnames.ora, sqlnet.ora, README files. The Wallet requires a password that will be used for PKCS12, PEM, and JKS keystores.
Step 3: Download ADBQuickStart.java and update the connection URL to point to the downloaded wallet location using TNS_ADMIN. The TNS alias, dbname_medium, is present in the tnsnames.ora file in the downloaded wallet. This chooses Oracle SSO wallets, which don’t require a password for the connection. To speed up connection setup, provide the connection URL shown below.

final String DB_URL="jdbc:oracle:thin:@dbname_medium?TNS_ADMIN=/Users/test/wallet_dbname/";

OR
Step 3: If you want to use other PKCS12, PEM, or JKS files, download TBD and update the connection URL. Copy the Mutual TLS URL from the OCI console by navigating to your Autonomous AI Database Details page and clicking on Database Connection. Under TLS Authentication, select Mutual TLS to copy the database connection string.
Step 4: If using PKCS12 files, please add the following line of code to update the provider. The ewallet.p12 created using the orapki tool has a different format than the one in the standard ewallet.p12 created using the keytool. In scenarios when the orapki tool is used to create PKCS12 files, you must update the provider to use OraclePKIProvider using the below line of code.

Security.insertProviderAt(new oracle.security.pki.OraclePKIProvider(), 1);

Step 5: Set the keystore related conection properties as shown below. Note that you need to select only one keystore type.

Option 1: Set wallet property as a system property, or add this to the ojdbc.properties file.   

oracle.net.wallet_location=${TNS_ADMIN}
oracle.net.wallet_password=<password_for_wallet>

Option 2: Set wallet property as a connection property

// For Oracle SSO Wallet
props.setProperty("oracle.net.wallet_location","D:\\keystore\\cwallet.sso"); 

// For PKCS12 wallet
props.setProperty("oracle.net.wallet_location","D:\\keystore\\ewallet.p12"); 
props.setProperty("oracle.net.wallet_password", password);

// For PEM files 
props.setProperty("oracle.net.wallet_location","D:\\keystore\\ewallet.pem"); 
props.setProperty("oracle.net.wallet_password", password);

// For JKS files 
props.setProperty("javax.net.ssl.trustStore","D:\\truststore\\truststore.jks");
props.setProperty("javax.net.ssl.trustStoreType", "JKS"); 
props.setProperty("javax.net.ssl.trustStorePassword","welcome123");
props.setProperty("javax.net.ssl.keyStore","D:\\keystore\\keystore.jks");
props.setProperty("javax.net.ssl.keyStoreType", "JKS"); 
props.setProperty("javax.net.ssl.keyStorePassword","welcome123");

Alternatively, 
props.put(OracleConnection.CONNECTION_PROPERTY_WALLET_LOCATION,"/home/user/cloud/cwallet.pem");
props.put(OracleConnection.CONNECTION_PROPERTY_WALLET_PASSWORD,"welcome123");

7.2 mTLS with On-Premise Database

For mTLS with the on-premises database, server authentication is addressed through “truststore”. The client needs to be authenticated on the server through the “keystore”. You can use any format of “keystore” as long as the provider for the same is available. It is a common practice to store server and client-side certificates in different locations. Therefore, you will need to specify a different path for both truststore and keystore wallets. Oracle SSO, PKCS12, PEM, or JKS keystores can be used to validate the client’s certificate.

Follow these steps for SSO, PKCS12, PEM, or JKS as the truststore

Step 1: Ensure the prerequisites are met. 
Step 2: Download the TBD and update the connection URL to point to your database.
Step 3: Ensure the corresponding truststore/wallets are located at a location accessible to the application, and remember the password for PKCS12, PEM, or JKS. Oracle SSO Wallets do not need a password if created using “auto-login” enabled. Note that only one type of certificate is required for establishing the connection.
Step 4: If using PKCS12 files, please add the following line of code to update the provider. The ewallet.p12 created using the orapki tool has a different format than the one in the standard ewallet.p12 created using the keytool. In scenarios when the orapki tool is used to create PKCS12 files, you must update the provider to use OraclePKIProvider using the below line of code.

Security.insertProviderAt(new oracle.security.pki.OraclePKIProvider(), 1);

Step 5: Set the truststore and keystore related connection properties as shown below. Note that you must select only one type of truststore. The password is the one used to create the truststore and keystores with the keytool or orapki tool.

// For Oracle SSO Wallets 
props.setProperty("javax.net.ssl.trustStore","D:\\truststore\\cwallet.sso");
props.setProperty("javax.net.ssl.trustStoreType", "SSO"); 
props.setProperty("javax.net.ssl.keyStore","D:\\truststore\\cwallet.sso");
props.setProperty("javax.net.ssl.keyStoreType", "SSO"); 

// For PKCS12 Wallets 
props.setProperty("javax.net.ssl.trustStore","D:\\truststore\\ewallet.p12");
props.setProperty("javax.net.ssl.trustStoreType", "PKCS12"); 
props.setProperty("javax.net.ssl.trustStorePassword","welcome123");
props.setProperty("javax.net.ssl.keyStore","D:\\truststore\\ewallet.p12");
props.setProperty("javax.net.ssl.keyStoreType", "PKCS12"); 
props.setProperty("javax.net.ssl.keyStorePassword","welcome123");

// For PEM files 
props.setProperty("javax.net.ssl.trustStore","D:\\truststore\\ewallet.pem");
props.setProperty("javax.net.ssl.trustStoreType", "PEM"); 
props.setProperty("javax.net.ssl.trustStorePassword","welcome123");
props.setProperty("javax.net.ssl.keyStore","D:\\truststore\\ewallet.pem");
props.setProperty("javax.net.ssl.keyStoreType", "PEM"); 
props.setProperty("javax.net.ssl.keyStorePassword","welcome123");

// For JKS files
props.setProperty("javax.net.ssl.trustStore","D:\\truststore\\truststore.jks");
props.setProperty("javax.net.ssl.trustStoreType", "JKS"); 
props.setProperty("javax.net.ssl.trustStorePassword","welcome123");
props.setProperty("javax.net.ssl.keyStore","D:\\truststore\\truststore.jks");
props.setProperty("javax.net.ssl.keyStoreType", "JKS"); 
props.setProperty("javax.net.ssl.keyStorePassword","welcome123");

Alternatively, you can use these properties to set it in the application code. 
props.put(OracleConnection.CONNECTION_PROPERTY_THIN_JAVAX_NET_SSL_TRUSTSTORE,"/home/user/cloud/ewallet.p12"); 
props.put(OracleConnection.CONNECTION_PROPERTY_THIN_JAVAX_NET_SSL_TRUSTSTORETYPE,"PKCS12"); 
props.put(OracleConnection.CONNECTION_PROPERTY_THIN_JAVAX_NET_SSL_KEYSTOREPASSWORD,"Welcome123");
props.put(OracleConnection.CONNECTION_PROPERTY_THIN_JAVAX_NET_SSL_KEYSTORE,"/home/user/cloud/ewallet.p12"); 
props.put(OracleConnection.CONNECTION_PROPERTY_THIN_JAVAX_NET_SSL_KEYSTORETYPE,"PKCS12"); 
props.put(OracleConnection.CONNECTION_PROPERTY_THIN_JAVAX_NET_SSL_KEYSTOREPASSWORD,"Welcome123");

8. Special Scenarios

In some scenarios, the keystore can contain multiple private keys, each with its own certificate for a distinct identity. Multiple certificates in a keystore provide flexibility for managing distinct identities or trust anchors, each stored under a unique alias. To specify the correct client certificate for the connection, use these connection properties.

  • oracle.net.ssl_certificate_alias
  • oracle.net.ssl_certificate_thumbprint
  • oracle.net.ssl_pem_private_key_index

9. New TLS Features in 26ai

Refer to Security Features under the blog Quick Peek into New Features/Capabilities from Oracle JDBC 23ai.”

10. Conclusion

TLS provides network security, including encryption, data integrity, and authentication for both the server and client tiers, using the latest cryptographic standards. Implementing SSL/TLS with the Oracle JDBC Thin Driver is essential for securing database communications in modern enterprise environments. This blog provides an overview of TLS support in the Oracle JDBC Thin driver for the Oracle AI Autonomous Database and the Oracle On-Premises database, and explains how it can be configured using multiple wallets, along with use cases and troubleshooting tips. By following the guidelines outlined in this blog, you can successfully implement secure, compliant, and performant database connectivity using SSL/TLS with the Oracle JDBC Thin Driver.

11. Troubleshooting Tips

#1:  Exception: java.sql.SQLException: Io exception: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find a valid certification path to the requested target.”:
Possible Cause: The client truststore does not contain the path to approve the certificate of the server (contained in the server’s wallet). 
Solution: You should also ensure that both sqlnet.ora and listener.ora are present and point to the same wallet location. If you have changed the wallet location in the “listener.ora”, you also need to restart the listener.

#2: java.security.KeyStoreException: SSO not found at java.base/java.security.KeyStore.getInstance(KeyStore.java:871) or java.security.NoSuchAlgorithmException: SSO KeyStore not available at java.base/sun.security.jca.GetInstance.getInstance(GetInstance.java:159)
Possible Cause: The connection property oracle.net.wallet_location is used in the code, indicating that Oracle Wallets are used for SSL authentication. This property allows the thin driver to load the required Oracle PKI provider from oraclepki.jar. But it fails to find the oraclepki.jar in the classpath and hence throws the error. 
Solution: Make sure to download oraclepki.jar and place it in the classpath. 

#3:  Exception in thread “main” java.sql.SQLException: ORA-17957: Unable to initialize the key store. (CONNECTION_ID=otCt3dSLRYOwiiig8LEAkQ==) …
Caused by: java.nio.file.NoSuchFileException: /home/user/cloud/cwallet.sso 
Possible Cause: The oraclepki.jar is on the classpath, which allows the driver to load the Oracle PKI provider; however, the driver cannot locate the actual cwallet file.sso required for SSL authentication specified in the oracle.net.wallet_locationproperty.
Solution: Make sure that the Oracle wallet file cwallet.sso is present in the path specified through the oracle.net.wallet_location property

#4:  Exception in thread “main” java.sql.SQLException: ORA-12506: TNS:listener rejected connection based on service ACL filtering (CONNECTION_ID=+Yt7xFOvRN2mMTPk5b0h6g==)
Possible Cause: The connections require TLS, but the required certificates for either one-way or mutual Authentication are not found.
Solution: Make sure to use either JKS or Oracle Wallets related connection properties that specify the location of the certificates required for either one-way or mutual authentication.