To access data in columns protected by column encryption from a Java application, use the EncJDBC driver to connect to your database. EncJDBC retrieves plaintext from encrypted columns with minimal configuration.
When you provide the master encryption key, the entire data transmission link is encrypted. The EncJDBC client automatically decrypts the data and returns plaintext that your application can display with minimal code changes.
Prerequisites
You have run a sensitive data detection scan to find columns that require encryption.
You have configured column encryption for the target database and set the permission for the database account to Ciphertext Permission (JDBC Decryption). For detailed instructions, see column encryption.
Connection details for the instance: hostname, port, database name, username, and password.
Generate an MEK
Value range: A 16-byte hexadecimal string, exactly 32 characters long.
Based on the key type you selected when you configured column encryption, you can use either a KMS Key or generate a local key as your MEK to decrypt the database.
KMS key
Ensure the KMS service is available when using a KMS key. Otherwise, the always-confidential client driver EncJDBC cannot function.
Obtain the endpoint of the KMS instance that owns the KMS key selected in your database column encryption configuration, along with the AccessKey ID and AccessKey secret of the Alibaba Cloud account or RAM user (which must have KMS decryption permission) to read this KMS key from the client. Follow these steps:
Log on to the console using an Alibaba Cloud account or a RAM user.
Local key
When the Encryption Method in your database column encryption configuration is set to Local Key, generate an MEK. For example: 00112233445566778899aabbccddeeff.
Common generation methods include password generators or random functions in programming languages.
For example:
On Linux, use the built-in OpenSSL tool by running
openssl rand -hex 16to generate a key.On Windows, install the OpenSSL software package.
Client integration instructions
Use JDK 1.8 or later for Java.
On the client side, switch the database connection driver to EncJDBC, update the database connection URL, and specify the MEK to access plaintext from encrypted database columns.
1. Install dependencies
Add the following dependency to your Maven project configuration file pom.xml.
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-cls-jdbc</artifactId>
<version>1.0.10-3</version>
</dependency>2. ConfigureMEK to connect to the database
The following methods describe how to configure the MEK: JDBC properties configuration, file configuration, and URL configuration. If you configure more than one method simultaneously, the priority order is: JDBC properties configuration > file configuration > URL configuration.
In URL configuration, separate multiple parameters with
&.In all configurations and connection methods below, the
MEKis processed locally on the client and securely sent to the server using envelope encryption to preventMEKleakage.
Choose to connect to the database using either a local key or a KMS key based on the Encryption method in your database column encryption configuration.
Connect to the database using a KMS key
If you use STS temporary credentials to retrieve a KMS-managed MEK, use the STS SDK to obtain the temporary credential STS token. For STS SDK examples, see STS SDK overview.
Do not hard code access credentials (AccessKey ID and AccessKey secret) directly in your application code. This example uses system environment variables to manage access credentials. For details, see Configure environment variables on Linux, macOS, and Windows.
JDBC properties configuration
Standard JDBC lets you set custom properties using Properties during connection. The following example shows how to configure JDBC properties and run JDBC:
// Prepare connection information such as hostname, port, database name, username, and password.
// ...
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";
// Retrieve access credentials (AccessKey ID and AccessKey secret) from environment variables.
String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
// If using STS temporary credentials to read the KMS key, also provide the obtained STS token.
// String stsToken = "yourSecurityToken";
// KMS instance endpoint. Use the public endpoint if public network access is enabled. Use the VPC endpoint for VPC access.
String kmsEndpoint = "kms.cn-hangzhou.aliyuncs.com";
Properties props = new Properties();
props.setProperty("user", username);
props.setProperty("password", password);
props.setProperty("ALIBABA_CLOUD_ACCESS_KEY_ID", accessKeyId);
props.setProperty("ALIBABA_CLOUD_ACCESS_KEY_SECRET", accessKeySecret);
props.setProperty("ALIBABA_CLOUD_KMS_ENDPOINT", kmsEndpoint);
// props.setProperty("ALIBABA_CLOUD_STS_TOKEN", "stsToken");
// Connection URL format for MySQL: "jdbc:mysql:encdb://%s:%s/%s".
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);
// Load the EncJDBC driver for MySQL.
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
// Get the database connection.
Connection connection = DriverManager.getConnection(dbUrl, props);
// ... Execute queries ...URL configuration
You can embed parameters for retrieving the KMS key directly in the URL, as shown below:
// Prepare connection information such as hostname, port, database name, username, and password.
// ...
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";
// Retrieve access credentials (AccessKey ID and AccessKey secret) from environment variables.
String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
// If using STS temporary credentials to read the KMS key, also provide the obtained STS token.
// String stsToken = "yourSecurityToken";
// KMS instance endpoint. Use the public endpoint if public network access is enabled. Use the VPC endpoint for VPC access.
String kmsEndpoint = "kms.cn-hangzhou.aliyuncs.com";
// Connection URL format for MySQL.
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s?ALIBABA_CLOUD_ACCESS_KEY_ID=%s&ALIBABA_CLOUD_ACCESS_KEY_SECRET=%s&ALIBABA_CLOUD_KMS_ENDPOINT=%s", hostname, port, dbname, accessKeyId, accessKeySecret, kmsEndpoint);
// With STS token.
// String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s?ALIBABA_CLOUD_ACCESS_KEY_ID=%s&ALIBABA_CLOUD_ACCESS_KEY_SECRET=%s&ALIBABA_CLOUD_KMS_ENDPOINT=%s&ALIBABA_CLOUD_STS_TOKEN=%s", hostname, port, dbname, accessKeyId, accessKeySecret, kmsEndpoint, stsToken);
// Load the EncJDBC driver for MySQL.
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
// Get the database connection.
Connection connection = DriverManager.getConnection(dbUrl, username, password);
// ... Execute queries ...Connect to the database using a local key
JDBC properties configuration
Standard JDBC lets you set custom properties using Properties during connection. The following example shows how to configure JDBC properties and run JDBC:
// Prepare connection information such as hostname, port, database name, username, and password.
// ...
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";
// Master encryption key.
String mek = "00112233445566778899aabbccddeeff";
Properties props = new Properties();
props.setProperty("user", username);
props.setProperty("password", password);
props.setProperty("MEK", mek);
// Connection URL format for MySQL: "jdbc:mysql:encdb://%s:%s/%s". For PostgreSQL, use "jdbc:postgresql:encdb://%s:%s/%s".
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);
// Load the EncJDBC driver for MySQL. For PostgreSQL, use "com.aliyun.encdb.postgresql.jdbc.EncDriver".
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
// Get the database connection.
Connection connection = DriverManager.getConnection(dbUrl, props);
// ... Execute queries ...File configuration
You can import parameters such as the required MEK through a configuration file.
File configuration applies only to local key MEKs.
You can set a property named encJdbcConfigFile in your project and set its value to the configuration file path (by default, the file encjdbc.conf is used). The content of the configuration file is as follows:
MEK=00112233445566778899aabbccddeeffYou can place the configuration file in one of two locations:
Put the file in the resources directory of your project, as shown below:
src main java resources encjdbc.confPut the file in the project root directory (the program’s runtime directory).
After setting up file configuration, no additional configuration is needed in your code, as shown below:
// Prepare connection information such as hostname, port, database name, username, and password.
// ...
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";
// Connection URL format for MySQL: "jdbc:mysql:encdb://%s:%s/%s". For PostgreSQL, use "jdbc:postgresql:encdb://%s:%s/%s".
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);
// Load the EncJDBC driver for MySQL. For PostgreSQL, use "com.aliyun.encdb.postgresql.jdbc.EncDriver".
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
// Get the database connection.
Connection connection = DriverManager.getConnection(dbUrl, username, password);
// ... Execute queries ...URL configuration
You can embed parameters such as the MEK directly in the URL, as shown below:
// Prepare connection information such as hostname, port, database name, username, and password.
// ...
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";
// Master encryption key.
String mek = "00112233445566778899aabbccddeeff";
// Connection URL format for MySQL: "jdbc:mysql:encdb://%s:%s/%s?MEK=%s". For PostgreSQL, use "jdbc:postgresql:encdb://%s:%s/%s?MEK=%s".
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s?MEK=%s", hostname, port, dbname, mek);
// Load the EncJDBC driver for MySQL. For PostgreSQL, use "com.aliyun.encdb.postgresql.jdbc.EncDriver".
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
// Get the database connection.
Connection connection = DriverManager.getConnection(dbUrl, username, password);
// ... Execute queries ...3. Query plaintext data from encrypted columns
After successfully connecting to the database, operate it just like a standard JDBC query. EncJDBC automatically decrypts encrypted columns and returns plaintext data.
Sample code:
// Execute the query.
// Create a query statement.
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM your_table_name");
// Traverse the result set.
while (resultSet.next()) {
for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {
System.out.print(rs.getString(i + 1));
System.out.print("\t");
}
System.out.print("\n");
}Troubleshooting
IllegalAccessError: cannot access class com.sun.crypto.provider.SunJCE
This error occurs because newer JDK versions restrict cross-module access by default. Add the following VM option when running your program:
--add-exports=java.base/com.sun.crypto.provider=ALL-UNNAMED
failed in mek provision: gcmEncrypt error
This is a known issue with Oracle JDK. Use one of the following fixes:
-
Switch to Amazon Corretto — a drop-in OpenJDK distribution that does not have this issue.
-
Add the BouncyCastle security provider to Oracle JDK:
-
Locate your JDK installation directory.
-
Open
<jdk-path>/conf/security/java.security. -
In the
List of providers and their preference orderssection, add: ``security.provider.14=org.bouncycastle.jce.provider.BouncyCastleProvider``
-