Column encryption driver (JDBC)

更新时间:
复制 MD 格式

Use the Alibaba Cloud column encryption driver (JDBC) to access encrypted data in your database from a Java application. The driver uses a valid master encryption key (MEK) to automatically and transparently decrypt ciphertext into plaintext.

Prerequisites

  • Column encryption must be enabled. For more information, see column encryption.

    Note

    After you enable column encryption, the rds_encdb extension is installed by default in the target database. You can run the following SQL statement to check the status of the rds_encdb extension: SELECT EXISTS (SELECT * FROM pg_extension WHERE extname = 'rds_encdb');

  • You must have the connection information for the encrypted database, including the hostname, port, database name, username, and password. To learn how to obtain the internal or public endpoint of an instance, see View and change the endpoints and port numbers.

  • The database user must have the ciphertext permission (JDBC decryption) for column encryption. For more information, see column encryption.

Usage notes

  • Securely store the MEK.

  • Use JDK 1.8 or a later version.

Procedure

Note

This topic uses a Maven-based Java project as an example.

Step 1: Configure Maven dependency

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

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

Step 2: Configure URL and MEK

Before accessing encrypted data with JDBC, configure parameters such as the MEK and the URL.

Parameter

Example

Description

MEK

00112233445566778899aabbccddeeff

A user-defined master encryption key.

  • You can generate a key using a tool like openssl rand -hex 16, a programming language's random function, or by obtaining one from a third-party Key Management Service (KMS).

  • Value range: A 16-byte hexadecimal string (32 characters).

Warning

For security, the database does not store, manage, generate, or back up your MEK. You are responsible for key generation and backup. Losing the MEK results in permanent loss of access to your encrypted data.

URL

jdbc:postgresql:encdb://%s:%s/%s

To use the column encryption driver, change the URL prefix to jdbc:postgresql:encdb://.

Configure the MEK

You can configure the MEK in three ways. If you configure more than one method in your JDBC connection, the priority is as follows: JDBC Properties configuration > File configuration > URL configuration.

Note
  • In the URL configuration method, you can concatenate multiple parameters using the ampersand (&) character.

  • In all three connection methods, the MEK is processed locally on the client and securely distributed to the server using envelope encryption, preventing its exposure.

JDBC properties

Standard JDBC lets you configure custom attributes in a Properties object when establishing a connection. For example:

// Prepare connection information, such as hostname, port, dbname, username, and password.
// ...
String mek="****";
Properties props = new Properties();
props.setProperty("user", username);
props.setProperty("password", password);
props.setProperty("MEK", mek);
String dbUrl = String.format("jdbc:postgresql:encdb://%s:%s/%s", hostname, port, dbname);
Connection connection = DriverManager.getConnection(dbUrl, props);
// ... Initiate a query ...
File

You can import parameters like the MEK from a configuration file. To do this, set the encJdbcConfigFile property to the file's path. If this property is not set, the driver uses the encjdbc.conf file by default.

The configuration file contains the following:

MEK=****

You can place the configuration file in one of the following two locations:

  • Place the encjdbc.conf file in the resources directory of your project.

  • Place the file in the project's root directory, which is the application's runtime directory.

Once the MEK is configured in a file, no extra code is needed. For example:

// Prepare connection information, such as hostname, port, dbname, username, and password.
// ...
String dbUrl = String.format("jdbc:postgresql:encdb://%s:%s/%s", hostname, port, dbname);
Connection connection = DriverManager.getConnection(dbUrl, username, password);
// ... Initiate a query ...
URL

You can embed parameters such as MEK and ENC_ALGO in the URL. For example:

// Prepare connection information, such as hostname, port, dbname, username, and password.
// ...
String mek="****";
String dbUrl = String.format("jdbc:postgresql:encdb://%s:%s/%s?MEK=%s", hostname, port, dbname, mek);
Connection connection = DriverManager.getConnection(dbUrl, username, password);
// ... Initiate a query ...

Code example

The following code shows a complete example of configuring the MEK by using JDBC Properties configuration. Before running this code, ensure column encryption is set up in the target database.

package org.example;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
public class Main {
    public static void main(String[] args) throws SQLException {
        // Update the following connection information (hostname, port, dbname, username, password) based on your actual environment.
        String hostname = "pgm-****.pg.rds.aliyuncs.com"; // The instance endpoint. Replace with your actual value.
        String port = "5432"; // The database port. Replace with your actual value.
        String dbname = "testdb"; // The database name. Replace with your actual value.
        String username = "user"; // The database username. Use a user that has the ciphertext permission (JDBC decryption).
        String password = "password"; // The password for the database user.
        
        // This is a sample key. We recommend using a stronger key to improve security.
        String MEK = "00112233445566778899aabbccddeeff";
        
       // Create database connection properties.
        Properties props = new Properties();
        props.setProperty("user", username);
        props.setProperty("password", password);
        props.setProperty("MEK", MEK);
        
        // Format the database connection URL.
        String dbUrl = String.format("jdbc:postgresql:encdb://%s:%s/%s", hostname, port, dbname);
        
        // Get the database connection using DriverManager.
        Connection connection = DriverManager.getConnection(dbUrl, props);
        
        // Execute a query to retrieve data from the test table.
        ResultSet rs = connection.createStatement().executeQuery("SELECT * FROM test_table");
        while (rs.next()) {
            for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) { // Column indexes start from 1.
                System.out.print(rs.getString(i) + "\t");
            }
            System.out.println(); // New line.
        }
        
        // Close resources.
        rs.close();  // Close the result set.
        connection.close(); // Close the connection.
    }
}