All Products
Search
Document Center

PolarDB:Integrate EncJDBC

Last Updated:Dec 05, 2025

To support seamless integration for your Java applications without code modifications, the PolarDB Always-confidential feature provides a dedicated client driver, Encrypted Java Database Connectivity (EncJDBC). EncJDBC automatically decrypts ciphertext and returns plaintext data. This process is transparent to the application. Your application can connect to PolarDB Always-confidential with just a few lines of configuration, and no changes to your existing business code are required.

Solution architecture

PolarDB Always-confidential is a dynamic encryption and decryption solution based on a database proxy. The core logic is that the proxy layer encrypts pre-configured sensitive fields in the query results before returning them to the client. The client application must use the dedicated EncJDBC driver to transparently decrypt the data upon receipt.

Workflow and role permissions

  1. Query request: The client application sends a standard SQL query to the PolarDB cluster endpoint through the EncJDBC driver.

  2. Proxy processing: The database proxy receives the request and forwards it to the backend database kernel for execution.

  3. On-the-fly encryption: As the query results are returned, the proxy layer checks whether they match a pre-set encryption policy. If a match is found, the sensitive fields in the result set are encrypted using the key that you specify from KMS or a self-managed key.

  4. Data return: The encrypted result set is returned to the client.

  5. Transparent decryption: The EncJDBC driver on the client automatically decrypts the ciphertext. The application receives plaintext data, and the entire process is transparent to the business code.

Query results vary based on the role of the database account

  • Super administrator: Query results are always in plaintext and are not affected by encryption policies. This is useful for database management and auditing.

  • Regular user: Query results are ciphertext. You must use the EncJDBC driver and the correct key to decrypt data on the client.

  • Other users: Query results are ciphertext and cannot be decrypted.

Limits

Before you implement this feature, review the following limits to assess whether the feature meets your business and technical architecture requirements.

  • Endpoint requirement: Encryption rules take effect only when you connect using a cluster endpoint or a custom endpoint. Connecting directly to the primary endpoint bypasses the proxy, which disables the encryption feature.

  • Key management: When you use a self-managed key, key rotation is not supported. You also risk key loss or leakage. If a key is lost, the corresponding encrypted data cannot be decrypted. You must establish strict security procedures to manage keys.

  • JDK version: You must use JDK 1.8 or later.

Use a KMS key

Step 1: Configure KMS access permissions

  1. Obtain an AccessKey pair: Obtain the AccessKey ID and AccessKey secret of a RAM user. This allows the application to obtain the master encryption key (MEK) that is managed by KMS.

    1. If you already have a suitable RAM user to access KMS, you can use that user.

    2. If you do not have a suitable RAM user, go to the RAM console. In the navigation pane on the left, choose Identity Management > Users. Click Create User and follow the on-screen instructions to create a user.

  2. Grant permissions to the RAM user

    1. Go to the RAM console. On the Permission Management > Access Policies page, click Create Access Policy. Switch to the script editor, copy the following content, and click OK. Enter a policy name and complete the creation.

      {
          "Version": "1",
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": "KMS:Decrypt",
                  "Resource": "*"
              }
          ]
      }
    2. In the RAM console, go to the Identity Management > Users page. Find the target RAM user, click Add Permissions in the Actions column, and grant it the newly created access policy. This allows PolarDB to dynamically decrypt data.

  3. Obtain the KMS instance endpoint

    • VPC endpoint (default): By default, keys in a KMS instance can be accessed only from within a VPC network. You can go to the KMS instance management page, select the region where the instance is located, find the target KMS instance, and click Details in the Actions column. Then, on the Basic Information tab, you can view the instance VPC endpoint.

    • Public endpoint: To access the key over the Internet, you must enable public access on the RD Multi-Account tab. After you enable public access, you can view the Public Endpoint on the Basic Information tab.

Step 2: Install dependencies

Add the following dependency to the pom.xml file of your Maven project.

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-cls-jdbc</artifactId>
    <version>1.0.10-1</version>
</dependency>
Note

When you add the Maven dependency, replace the value of version as needed. You can check for the latest version of aliyun-cls-jdbc on the official website.

Step 3: Configure the MEK to connect to the database

You can configure the MEK using JDBC properties, a file, or a URL. If you configure your JDBC using two or more methods, the priority is as follows: JDBC properties configuration > File configuration > URL configuration.

Note
  • In the following configuration and connection methods, the MEK is processed locally on the client and sent to the server using a secure method (envelope encryption) to ensure that the MEK is not leaked.

  • Do not hard code the AccessKey pair (AccessKey ID and AccessKey secret) in your business code. This example uses system environment variables to manage the AccessKey pair. For more information, see Configure environment variables on Linux, macOS, and Windows systems.

  • To use a temporary STS access credential to obtain the MEK that is managed by KMS, you can use an STS SDK to obtain a temporary credential, the Security Token Service (STS) token. For STS SDK examples, see Overview of STS SDKs.

JDBC properties configuration

When a standard JDBC connection is established, you can set custom attributes using a Properties object.

Example

// Prepare connection information such as the endpoint (hostname), port, database instance name (dbname), username, and password.
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";

// Get the 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 you use a temporary STS access credential to read the KMS key, you also need to fill in the obtained Security Token.
// String stsToken= "yourSecurityToken";

// For the KMS instance endpoint, use the public endpoint for public network access. Use the instance VPC endpoint for access within a VPC network.
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");

// The following is the connection URL format for a MySQL database: "jdbc:mysql:encdb://%s:%s/%s".
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);

// The following loads the EncJDBC driver for a MySQL database.
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");

// Get the database connection.
Connection connection = DriverManager.getConnection(dbUrl, props);

// ... Initiate a query ...
URL configuration

You can embed the parameters for obtaining the KMS key in the URL.

Example

// Prepare connection information such as the endpoint (hostname), port, database instance name (dbname), username, and password.
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";

// Get the 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 you use a temporary STS access credential to read the KMS key, you also need to fill in the obtained Security Token.
// String stsToken= "yourSecurityToken";

// For the KMS instance endpoint, use the public endpoint for public network access. Use the instance VPC endpoint for access within a VPC network.
String kmsEndpoint = "your-kms-endpoint";

// The following is the connection URL format for a MySQL database.
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);
// Use an 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);

// The following loads the EncJDBC driver for a MySQL database.
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");

// Get the database connection.
Connection connection = DriverManager.getConnection(dbUrl, username, password);

// ... Initiate a query ...

Step 4: Query plaintext data from encrypted columns

After you successfully connect to the database, you can perform database operations as you would with a regular JDBC query. EncJDBC automatically decrypts encrypted columns and returns plaintext data.

Example

// 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");
}

Appendix: Complete code example

Note

This example uses Maven version 3.9.9 and the IntelliJ IDEA Community Edition 2024.1.2 development tool.

import java.sql.*;
import java.util.Properties;

public class EncryptedColumnAccess {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        // Update the following connection information with your instance details, such as endpoint (hostname), port, database instance name (dbname), username, and password.
        String hostname = "your-hostname";
        String port = "your-port";
        String dbname = "your-database-name";
        String username = "your-username";
        String password = "your-password";

        // Get the 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 you use a temporary STS access credential to read the KMS key, you also need to fill in the obtained Security Token.
        // String stsToken= "yourSecurityToken";

        // For the KMS instance endpoint, use the public endpoint for public network access. Use the instance VPC endpoint for access within a VPC network.
        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");

        // The connection URL format for a MySQL database is "jdbc:mysql:encdb://%s:%s/%s".
        String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);

        // Load the EncJDBC driver.
        Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");

        // Get the database connection.
        Connection connection = DriverManager.getConnection(dbUrl, props);

        // Initiate a query.
        try {
            // Create a query statement.
            Statement statement = connection.createStatement();
            ResultSet resultSet = statement.executeQuery("SELECT * FROM users");

            // Traverse the result set.
            while (resultSet.next()) {
                int id = resultSet.getInt("id");
                String name = resultSet.getString("username");
                String phone = resultSet.getString("phone");

                // Process other fields based on your table schema.
                System.out.println("ID: " + id + ", Name: " + name + ", Phone: " + phone);
            }

            // Close resources.
            resultSet.close();
            statement.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Use a local key

Step 1: Generate an MEK

Warning

The master encryption key (MEK) is the root credential that you use to authorize clients to access encrypted data. For security reasons, the encrypted database does not hold or manage your MEK. It also does not provide MEK generation or backup services. You must generate the MEK yourself. The storage and management of the MEK are critical to database security. We recommend that you back up your MEK properly.

MEK: The MEK is transmitted from the client to the database server using a secure asymmetric key encryption protocol. This allows the server and client to share the same key for secure data transmission through symmetric encryption.

Valid value: a 16-byte hexadecimal string that is 32 characters in length. For example, 00112233445566778899aabbccddeeff.

Common generation methods: You can use password generation tools or the random function in a programming language.

Example

  • On Linux, you can use the built-in OpenSSL tool. Run openssl rand -hex 16 to generate a key.

    # Use OpenSSL to generate a secure random key
    openssl rand -hex 16
    # Example output: 11ce9a9489fab7355cf710837cea5d5b
  • On Windows, you can install the OpenSSL package.

Step 2: Install dependencies

Add the following dependency to the pom.xml file of your Maven project.

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-cls-jdbc</artifactId>
    <version>1.0.10-1</version>
</dependency>
Note

When you add the Maven dependency, replace the value of version as needed. You can check for the latest version of aliyun-cls-jdbc on the official website.

Step 3: Configure the MEK to connect to the database

You can configure the MEK using JDBC properties, a file, or a URL. If you configure your JDBC using two or more methods, the priority is as follows: JDBC properties configuration > File configuration > URL configuration.

Note

In the following configuration and connection methods, the MEK is processed locally on the client and sent to the server using a secure method (envelope encryption) to ensure that the MEK is not leaked.

JDBC properties configuration

When a standard JDBC connection is established, you can set custom attributes using a Properties object.

Example

// Prepare connection information such as the endpoint (hostname), port, database instance name (dbname), username, and password.
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";

// Customer master key.
String mek = "00112233445566778899aabbccddeeff"; 

Properties props = new Properties();
props.setProperty("user", username);
props.setProperty("password", password);
props.setProperty("MEK", mek);

// The connection URL format for a MySQL database is "jdbc:mysql:encdb://%s:%s/%s".
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);

// Load the EncJDBC driver for a MySQL database.
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");

// Get the database connection.
Connection connection = DriverManager.getConnection(dbUrl, props);

// ... Initiate a query ...
File configuration
Note

The file configuration method is applicable only to configuring a local MEK.

You can import the required MEK and other parameters from a configuration file. In your project, set a property named encJdbcConfigFile and set its value to the path of the configuration file. If you do not specify a path, the system uses the encjdbc.conf file by default. The following code provides the content of the configuration file:

MEK=00112233445566778899aabbccddeeff

Example

  1. You can specify the location of the configuration file in one of the following two ways:

    • Place the file in the resources directory of your project, as shown in the following figure:

      image

    • Place the file in the root directory of the project, which is the runtime directory of the program.

  2. After you configure the file, you do not need to make additional configurations in your program, as shown in the following code:

    // Prepare connection information such as the endpoint (hostname), port, database instance name (dbname), username, and password.
    String hostname = "your-hostname";
    String port = "your-port";
    String dbname = "your-database-name";
    String username = "your-username";
    String password = "your-password";
    
    // The connection URL format for a MySQL database is "jdbc:mysql:encdb://%s:%s/%s".
    String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);
    
    // Load the EncJDBC driver for a MySQL database.
    Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
    
    // Get the database connection.
    Connection connection = DriverManager.getConnection(dbUrl, username, password);
    
    // ... Initiate a query ...
URL configuration

You can embed the MEK and other parameters in the URL.

Example

// Prepare connection information such as the endpoint (hostname), port, database instance name (dbname), username, and password.
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";

 // Customer master key.
String mek = "00112233445566778899aabbccddeeff";

// The connection URL format for a MySQL database is "jdbc:mysql: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 a MySQL database.
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");

// Get the database connection.
Connection connection = DriverManager.getConnection(dbUrl, username, password);

// ... Initiate a query ...

Step 4: Query plaintext data from encrypted columns

After you successfully connect to the database, you can perform database operations as you would with a regular JDBC query. EncJDBC automatically decrypts encrypted columns and returns plaintext data.

Example

// 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");
}

Appendix: Complete code example

Note

This example uses Maven version 3.9.9 and the IntelliJ IDEA Community Edition 2024.1.2 development tool.

import java.sql.*;
import java.util.Properties;

public class EncryptedColumnAccess {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        // Update the following connection information with your instance details, such as endpoint (hostname), port, database instance name (dbname), username, and password.
        String hostname = "your-hostname";
        String port = "your-port";
        String dbname = "your-database-name";
        String username = "your-username";
        String password = "your-password";
        
        // This is just an example. We recommend using a more complex key.
        String mek="00112233445566778899aabbccddeeff";

        Properties props = new Properties();
        props.setProperty("user", username);
        props.setProperty("password", password);
        props.setProperty("MEK", mek);
        
        // The connection URL format for a MySQL database is "jdbc:mysql:encdb://%s:%s/%s".
        String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);

        // Load the EncJDBC driver.
        Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");

        // Get the database connection.
        Connection connection = DriverManager.getConnection(dbUrl, props);

        // Initiate a query.
        try {
            // Create a query statement.
            Statement statement = connection.createStatement();
            ResultSet resultSet = statement.executeQuery("SELECT * FROM users");

            // Traverse the result set.
            while (resultSet.next()) {
                int id = resultSet.getInt("id");
                String name = resultSet.getString("username");
                String phone = resultSet.getString("phone");

                // Process other fields based on your table schema.
                System.out.println("ID: " + id + ", Name: " + name + ", Phone: " + phone);
            }

            // Close resources.
            resultSet.close();
            statement.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

FAQ

When I integrate EncJDBC, I receive the error Code: Forbidden.KeyNotFound; Message: code: 404, The specified Key is not found. What should I do?

Check whether the KMS instance endpoint is correctly set in your application.

  • Check the application environment: KMS instance endpoints are different for VPCs and public networks.

    • VPC endpoint (default): By default, keys in a KMS instance can be accessed only from within a VPC network. You can go to the KMS instance management page, select the region where the instance is located, find the target KMS instance, and click Details in the Actions column. Then, on the Basic Information tab, you can view the instance VPC endpoint.

    • Public endpoint: To access the key over the Internet, you must enable public access on the RD Multi-Account tab. After you enable public access, you can view the Public Endpoint on the Basic Information tab.

  • Check the KMS instance region

    • Adjust the endpoint based on your KMS instance region. For example, the public endpoint for China (Hangzhou) should be kms.cn-hangzhou.aliyuncs.com, and the public endpoint for China (Beijing) should be kms.cn-beijing.aliyuncs.com.

When I integrate EncJDBC, I receive the error Code: UnsupportedOperation; Message: code: 400, This action is not supported. What should I do?

This error may occur for the following reasons. Check them one by one.

  • You might be using the master key of a default key instead of a KMS customer master key.

    Note

    Your default master key can be used only for server-side encryption by cloud products. It cannot be used for your client-side data encryption. To encrypt data on the client side for PolarDB Always-confidential, you must create an instance to purchase a software-based or hardware-based customer master key (CMK).

  • The KMS instance does not have public network access enabled.

When I integrate EncJDBC, I receive the error Code: Forbidden.NoPermission; Message: code: 403, This operation for XXX is forbidden by permission system. What should I do?

Your AccessKey pair (AccessKey ID and AccessKey secret) may not have the required permissions to access KMS. Grant the KMS:Decrypt permission so that PolarDB can dynamically decrypt data.

  1. Go to the RAM console. On the Permission Management > Access Policies page, click Create Access Policy. Switch to the script editor, copy the following content, and click OK. Enter a policy name and complete the creation.

    {
        "Version": "1",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": "KMS:Decrypt",
                "Resource": "*"
            }
        ]
    }
  2. In the RAM console, go to the Identity Management > Users page. Find the target RAM user, click Add Permissions in the Actions column, and grant it the newly created access policy. This allows PolarDB to dynamically decrypt data.