EncJDBC (Encrypted Java Database Connectivity) is a dedicated JDBC driver for PolarDB's Confidential database feature. Add it to your Java project and your application receives plaintext data automatically — no changes to existing business logic required.
How it works
The Confidential database feature encrypts sensitive columns at the database proxy layer, not inside the database engine itself. The flow works as follows:
Your application sends a standard SQL query through the EncJDBC driver to a PolarDB cluster endpoint.
The database proxy forwards the query to the backend database.
As results are returned, the proxy checks each row against predefined encryption policies. Matching sensitive fields are encrypted using a key from Key Management Service (KMS) or a self-managed key.
The encrypted result set is returned to the EncJDBC driver.
EncJDBC decrypts the ciphertext locally on the client. Your application receives plaintext — the entire process is transparent to your code.
Query results by account role
The data a database account receives depends on its role:
| Role | Query result | Can decrypt? |
|---|---|---|
| Super administrator | Always plaintext | N/A — encryption policies do not apply |
| Regular user | Ciphertext | Yes, with EncJDBC and the correct key |
| Other users | Ciphertext | No |
Limitations
Review these constraints before implementing EncJDBC:
Endpoint type: Encryption policies apply only when connecting via a cluster endpoint or a custom endpoint. Connecting directly to the primary endpoint bypasses the database proxy, which disables encryption entirely.
JDK version: JDK 1.8 or later is required.
Key rotation (self-managed key only): Key rotation is not supported for self-managed keys. If a self-managed key is lost, all data encrypted with it becomes permanently unrecoverable. Establish strict key backup and management procedures before choosing this option.
Choose a key management approach
Two key management approaches are available:
| Approach | Key storage | Key rotation | Recommended for |
|---|---|---|---|
| KMS key | Alibaba Cloud KMS | Supported | Production workloads |
| Local key (self-managed) | Your own infrastructure | Not supported | Testing or air-gapped environments |
The sections below walk through each approach. Start with the KMS key approach if you are setting up a production environment.
Use a KMS key
Prerequisites
Before you begin, make sure you have:
A PolarDB cluster with the Confidential database feature enabled
A RAM user with an AccessKey pair (
AccessKeyIdandAccessKeySecret)A KMS instance with a customer master key (CMK) — not a default master key
The default master key is for server-side encryption by Alibaba Cloud services only. To encrypt data on the client side with EncJDBC, create a KMS instance and purchase a software-based or hardware-based CMK.
Step 1: Grant the RAM user KMS decrypt permission
Go to the RAM console. In the left navigation pane, choose Permission Management > Access Policies, then click Create Access Policy.
Switch to the script editor, paste the following policy, then click OK. Enter a policy name to finish.
{ "Version": "1", "Statement": [ { "Effect": "Allow", "Action": "KMS:Decrypt", "Resource": "*" } ] }In the left navigation pane, choose Identity Management > Users. Find the target RAM user, click Add Permissions in the Actions column, and attach the policy you just created.
Step 2: Get your KMS instance endpoint
KMS endpoints differ by network type:
VPC endpoint (default): Keys in a KMS instance are accessible only from within a virtual private cloud (VPC) by default. Go to the KMS instance management page, find your KMS instance, click Details in the Actions column, then view the endpoint on the Basic Information tab.
Public endpoint: To access KMS over the Internet, enable public access on the RD Multi-Account tab. The public endpoint then appears on the Basic Information tab.
Use the endpoint that matches your application's network environment. For example, the public endpoint for China (Hangzhou) is kms.cn-hangzhou.aliyuncs.com; for China (Beijing), it is kms.cn-beijing.aliyuncs.com.
Step 3: Add the Maven dependency
Add the following to your project's pom.xml:
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-cls-jdbc</artifactId>
<version>1.0.10-1</version>
</dependency>Check the Maven repository for the latest version and replace the value above as needed.
Step 4: Connect using EncJDBC
All three configuration methods use the same JDBC URL format: jdbc:mysql:encdb://<hostname>:<port>/<dbname>. The EncJDBC driver class is com.aliyun.encdb.mysql.jdbc.EncDriver.
If you configure KMS credentials using more than one method, the priority is: JDBC properties > file > URL parameters.
The master encryption key (MEK) never leaves the client as plaintext. EncJDBC transmits the MEK to the server using envelope encryption (asymmetric key encryption), so only the server can unwrap it for symmetric data encryption.
Never hard-code the AccessKey pair in your source code. Use environment variables instead, as shown in the examples below. For details, see Configure environment variables.
Option A: JDBC properties (recommended)
Pass credentials through a Properties object at connection time:
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";
// Read credentials from environment variables — never hard-code these.
String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
// For temporary STS credentials, also set the Security Token Service (STS) token:
// String stsToken = System.getenv("ALIBABA_CLOUD_STS_TOKEN");
// Use the VPC endpoint when running inside a VPC, or the public endpoint otherwise.
String kmsEndpoint = "your-kms-endpoint";
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);
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
Connection connection = DriverManager.getConnection(dbUrl, props);Option B: URL parameters
Embed the credentials directly in the connection URL. Use this approach when your framework constructs the URL automatically and does not expose a Properties object:
String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
String kmsEndpoint = "your-kms-endpoint";
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
);
// For STS credentials, append: &ALIBABA_CLOUD_STS_TOKEN=<token>
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
Connection connection = DriverManager.getConnection(dbUrl, username, password);Step 5: Query encrypted columns
Once connected, use standard JDBC operations. EncJDBC decrypts encrypted columns and returns plaintext transparently:
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM your_table_name");
while (resultSet.next()) {
for (int i = 0; i < resultSet.getMetaData().getColumnCount(); i++) {
System.out.print(resultSet.getString(i + 1));
System.out.print("\t");
}
System.out.print("\n");
}Complete example (KMS key)
This example was tested with Maven 3.9.9 and IntelliJ IDEA Community Edition 2024.1.2.
import java.sql.*;
import java.util.Properties;
public class EncryptedColumnAccess {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";
// Read KMS credentials from environment variables.
String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
// String stsToken = System.getenv("ALIBABA_CLOUD_STS_TOKEN"); // For STS credentials.
// Use the VPC endpoint inside a VPC, or the public endpoint for Internet access.
String kmsEndpoint = "your-kms-endpoint";
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);
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
Connection connection = DriverManager.getConnection(dbUrl, props);
try {
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM users");
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("username");
String phone = resultSet.getString("phone");
System.out.println("ID: " + id + ", Name: " + name + ", Phone: " + phone);
}
resultSet.close();
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}Use a local key
Use a self-managed MEK when you cannot use KMS — for example, in air-gapped environments. Review the limitations for this approach before proceeding.
Step 1: Generate an MEK
The Confidential database feature does not store or manage your MEK. If the key is lost, all data encrypted with it becomes permanently unrecoverable. Back up the key securely before using it.
The MEK must be a 32-character hexadecimal string (16 bytes). For example: 00112233445566778899aabbccddeeff.
Generate one using OpenSSL:
Linux: You can use the built-in OpenSSL tool.
# Generate a cryptographically secure random key openssl rand -hex 16 # Example output: 11ce9a9489fab7355cf710837cea5d5bWindows: Install the OpenSSL package and run the same command.
Step 2: Add the Maven dependency
Same dependency as the KMS approach:
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-cls-jdbc</artifactId>
<version>1.0.10-1</version>
</dependency>Check the Maven repository for the latest version.
Step 3: Connect using EncJDBC
Three configuration methods are available for the local MEK. Priority order: JDBC properties > file > URL parameters.
The MEK is transmitted to the server using envelope encryption, so it never travels as plaintext.
Option A: JDBC properties
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";
// Use a strong, randomly generated key — the value below is for illustration only.
String mek = "00112233445566778899aabbccddeeff";
Properties props = new Properties();
props.setProperty("user", username);
props.setProperty("password", password);
props.setProperty("MEK", mek);
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
Connection connection = DriverManager.getConnection(dbUrl, props);Option B: Configuration file
File-based configuration is available for local keys only.
Create a file named encjdbc.conf (the default name) with the following content:
MEK=00112233445566778899aabbccddeeffPlace the file in one of two locations:
The
resourcesdirectory of your project:
The root directory of your project (the program's runtime working directory).
No additional code changes are needed. The connection code works the same as standard JDBC:
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
Connection connection = DriverManager.getConnection(dbUrl, username, password);To use a custom file path, set the encJdbcConfigFile property to the file path before connecting.
Option C: URL parameters
String mek = "00112233445566778899aabbccddeeff";
String dbUrl = String.format(
"jdbc:mysql:encdb://%s:%s/%s?MEK=%s",
hostname, port, dbname, mek
);
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
Connection connection = DriverManager.getConnection(dbUrl, username, password);Step 4: Query encrypted columns
Same as the KMS approach — EncJDBC handles decryption transparently:
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM your_table_name");
while (resultSet.next()) {
for (int i = 0; i < resultSet.getMetaData().getColumnCount(); i++) {
System.out.print(resultSet.getString(i + 1));
System.out.print("\t");
}
System.out.print("\n");
}Complete example (local key)
This example was tested with Maven 3.9.9 and IntelliJ IDEA Community Edition 2024.1.2.
import java.sql.*;
import java.util.Properties;
public class EncryptedColumnAccess {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";
// Use a strong, randomly generated key — the value below is for illustration only.
String mek = "00112233445566778899aabbccddeeff";
Properties props = new Properties();
props.setProperty("user", username);
props.setProperty("password", password);
props.setProperty("MEK", mek);
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
Connection connection = DriverManager.getConnection(dbUrl, props);
try {
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM users");
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("username");
String phone = resultSet.getString("phone");
System.out.println("ID: " + id + ", Name: " + name + ", Phone: " + phone);
}
resultSet.close();
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}Troubleshooting
Forbidden.KeyNotFound (HTTP 404)
The KMS instance endpoint in your configuration is incorrect or unreachable from your application's network.
Check two things:
Network match: VPC endpoints are accessible only from within a VPC; public endpoints require Internet access. Make sure the endpoint type matches where your application runs.
Region match: The endpoint must match the region of your KMS instance. For example, use
kms.cn-hangzhou.aliyuncs.comfor China (Hangzhou) andkms.cn-beijing.aliyuncs.comfor China (Beijing).
To find the correct endpoint, go to the KMS instance management page, find your instance, click Details, then check the Basic Information tab.
UnsupportedOperation (HTTP 400)
Two possible causes:
Wrong key type: You are using a default master key instead of a customer master key (CMK). Default master keys are for server-side encryption by Alibaba Cloud services and cannot be used for client-side encryption with EncJDBC. Create a KMS instance and purchase a software-based or hardware-based CMK.
Public access not enabled: Your application is trying to reach KMS over the Internet, but public access is not enabled on the KMS instance. Enable it on the RD Multi-Account tab.
Forbidden.NoPermission (HTTP 403)
The AccessKey pair does not have KMS:Decrypt permission. Grant the permission by creating an access policy and attaching it to the RAM user:
Go to the RAM console. Choose Permission Management > Access Policies, click Create Access Policy, switch to the script editor, and paste the following:
{ "Version": "1", "Statement": [ { "Effect": "Allow", "Action": "KMS:Decrypt", "Resource": "*" } ] }Click OK, enter a policy name, and save.
Choose Identity Management > Users, find the RAM user, and click Add Permissions in the Actions column. Attach the policy you just created.