All Products
Search
Document Center

PolarDB:Integrate EncJDBC

Last Updated:Mar 28, 2026

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:

  1. Your application sends a standard SQL query through the EncJDBC driver to a PolarDB cluster endpoint.

  2. The database proxy forwards the query to the backend database.

  3. 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.

  4. The encrypted result set is returned to the EncJDBC driver.

  5. 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:

RoleQuery resultCan decrypt?
Super administratorAlways plaintextN/A — encryption policies do not apply
Regular userCiphertextYes, with EncJDBC and the correct key
Other usersCiphertextNo

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:

ApproachKey storageKey rotationRecommended for
KMS keyAlibaba Cloud KMSSupportedProduction workloads
Local key (self-managed)Your own infrastructureNot supportedTesting 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 (AccessKeyId and AccessKeySecret)

  • 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

  1. Go to the RAM console. In the left navigation pane, choose Permission Management > Access Policies, then click Create Access Policy.

  2. 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": "*"
            }
        ]
    }
  3. 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.
Important

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

Warning

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: 11ce9a9489fab7355cf710837cea5d5b
  • Windows: 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=00112233445566778899aabbccddeeff

Place the file in one of two locations:

  • The resources directory of your project:

    image

  • 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:

  1. 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.

  2. Region match: The endpoint must match the region of your KMS instance. For example, use kms.cn-hangzhou.aliyuncs.com for China (Hangzhou) and kms.cn-beijing.aliyuncs.com for 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:

  1. 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.

  2. Choose Identity Management > Users, find the RAM user, and click Add Permissions in the Actions column. Attach the policy you just created.