This topic describes how to use the always-confidential database feature from a client.
Prerequisites
The always-confidential database feature is enabled for the database. For more information, see Enable the always-confidential database feature.
Sensitive data is defined. For more information, see Define sensitive data.
The information that is used to connect to the always-confidential database is obtained. Before you connect to an always-confidential database from your client, you must obtain the connection information of the always-confidential database, including the domain name (host), port number (port), database name (dbname), username (username), and password (password). For more information, see View or apply for an endpoint.
In this topic, a Java application is used as an example. Make sure that a Java development environment is installed. We recommend that you use Java
1.8or later, Maven3.9.2, andIntelliJ IDEA Community Edition 2022.3.2.
Usage notes
Make sure that your master encryption key (MEK) is securely stored.
Examples
The always-confidential database feature encrypts the sensitive data in the query results. Applications can use the always-confidential database feature from the following types of clients.
Connection method | Description | Business code modification required | |
Application | EncJDBC | EncJDBC automatically identifies the data types for encryption and encrypts or decrypts data. | No. This method is recommended. |
EncDB SDK | Applications can use the functions provided by the EncDB SDK to encrypt or decrypt data. | Yes. | |
psql | The psql tool is a command line tool that allows you to query data in databases. psql obtains only ciphertext data. | No. You do not need to modify the business code because psql is used only for queries. | |
Visual and interactive tools such as the Data Management (DMS) console | |||
EncJDBC
Download drivers and configure dependencies
Download the EncJDBC driver.
EncJDBCdepends on PostgreSQL drivers provided by the community.PolarDB for PostgreSQL minor version
Version of EncDB on the PolarDB for PostgreSQL cluster
EncDB dependency package on the client
PolarDB for PostgreSQL 14: 20231030 (14.9.14.0) or later
1.1.13
Configure Maven dependencies.
NoteIn this section, Maven is used to configure the client.
Run the following command to install the
EncJDBCdependency package to your on-premises repository:mvn install:install-file -DgroupId=com.alibaba.encdb -DartifactId=<Name of the installed JAR package> -Dversion=<Version of the installed JAR package> -Dpackaging=jar -Dfile=<File name of the installed JAR package>Example:
mvn install:install-file -DgroupId=com.alibaba.encdb -DartifactId=encjdbc -Dversion=1.0.6 -Dpackaging=jar -Dfile=D:\encdb\libs\encjdbc-1.0.6.jarNoteIn this example, the EncDB dependency package is stored in the
D:\encdb\libspath.In this example, Maven
3.9.2is used. If you use an earlier version of Maven, upgrade the Maven version and try again.
After you install the
EncJDBCdependency package in your on-premises repository, add the following dependencies to the pom.xml configuration file of your Maven project:<dependencies> ... <dependency> <groupId>com.alibaba.encdb</groupId> <artifactId>encjdbc</artifactId> <version>1.0.6</version> </dependency> <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.62</version> </dependency> <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk15on</artifactId> <version>1.62</version> </dependency> <dependency> <groupId>com.alibaba.fastjson2</groupId> <artifactId>fastjson2</artifactId> <version>2.0.2</version> </dependency> <!-- https://mvnrepository.com/artifact/org.postgresql/postgresql --> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>42.2.23</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>24.1.1-jre</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.4</version> </dependency> <dependency> <groupId>org.jgrapht</groupId> <artifactId>jgrapht-core</artifactId> <!-- jgrapht does not support java 1.8 since 1.5.0 --> <version>1.4.0</version> </dependency> ... </dependencies>
Query data from the client (sample code)
The sample code in this section is for demonstration only. In the actual business code, do not set the password and mek parameters to values in plaintext. We recommend that you configure the parameters by using methods such as external configuration files and environment variables before you reference the parameters in the code.
URL configuration description
You can use
EncJDBCin the same manner that you use Java Database Connectivity (JDBC). Before you useEncJDBC, you must perform the following configuration to ensure data security:// The connection information such as the domain name (hostname), port number (port), database name (dbname), username (username), and password (password). // For more information, see the "Data security-related parameters" section of this topic. String mek=...; String encAlgo=...; String dbUrl = String.format("encjdbc:postgresql://%s:%s/%s?mek=%s&enc_algo=%s", hostname, port, dbname, mek, encAlgo); Class.forName("com.alibaba.encdb.encjdbc.EncDriver"); Connection dbConnection = DriverManager.getConnection(dbUrl, username, password); // ... Initiate a query ...NoteYou can use ampersands (
&) to concatenate multiple parameters.The
mekparameter and other parameters are configured on the client side and transmitted to the server side by using envelope encryption. In the process, the confidentiality of themekvalue is ensured.
Complete sample code
// The connection information of your cluster, including the domain name (hostname), port number (port), database name (dbname), username (username), and password (password). String hostname = "hostname"; String port = "port"; String dbname = "db"; String username = "user"; String password = "password"; String mek="00112233445566778899aabbccddeeff"; // This is an example value. We recommend that you use a more complex MEK. String encAlgo="SM4_128_CBC"; String dbUrl = String.format("encjdbc:postgresql://%s:%d/%s?mek=%s&enc_algo=%s", hostname, port, dbname, mek, encAlgo); Class.forName("com.alibaba.encdb.encjdbc.EncDriver"); Connection dbConnection = DriverManager.getConnection(dbUrl, username, password); // create table dbConnection.createStatement().executeUpdate("DROP TABLE IF EXISTS example"); dbConnection.createStatement().executeUpdate("CREATE TABLE example (id INTEGER, name VARCHAR, price enc_int4, miles enc_float4, secret enc_text, PRIMARY KEY (id))"); // insert data PreparedStatement stmt = dbConnection.prepareStatement("INSERT INTO example (id, name, price, miles, secret) VALUES(?,?,?,?,?)"); int price = 1234; float miles = 12.34f; String secret = "aliyun"; stmt.setInt(1, 1); stmt.setString(2, "name"); stmt.setInt(3, price); stmt.setFloat(4, miles); stmt.setString(5, secret); stmt.execute(); // check plaintext data String sqlCmd = "SELECT * FROM example WHERE price > ?"; PreparedStatement stmt = dbConnection.prepareStatement(sqlCmd); stmt.setInt(1, 100); ResultSet rs = stmt.executeQuery(); while (rs.next()){ int id = rs.getInt(1); String name = rs.getString(2); int price = rs.getInt(3); float miles = rs.getFloat(4); String secret = rs.getString(5); System.out.println(id + ", " + name + ", " + price + ", " + miles + ", " + secret); }Sample output:
1, name, 1234, 12.34, aliyun
In the preceding example for EncJDBC, only the driver loading and URL configurations are modified. Other data operations can be performed in the same manner as common database operations are performed. You do not need to modify business code.
EncDB SDK
Download drivers and configure dependencies
Download the EncDB SDK driver.
The
EncDB SDKdepends on PostgreSQL drivers provided by the community.PolarDB for PostgreSQL minor version
Version of EncDB on the PolarDB for PostgreSQL cluster
EncDB dependency package on the client
PolarDB for PostgreSQL 14: 20231030 (14.9.14.0) or later
1.1.13
Configure Maven dependencies.
NoteIn this section, Maven is used to configure the client.
Run the following command to install the
EncDB SDKdependency package to your on-premises repository:mvn install:install-file -DgroupId=com.alibaba.encdb -DartifactId=<Name of the installed JAR package> -Dversion=<Version of the installed JAR package> -Dpackaging=jar -Dfile=<File name of the installed JAR package>Example:
mvn install:install-file -DgroupId=com.alibaba.encdb -DartifactId=encjdbc -Dversion=1.2.12 -Dpackaging=jar -Dfile=D:\encdb\libs\libencdb-1.2.12.jarNoteIn this example, the EncDB dependency package is stored in the
D:\encdb\libspath.In this example, Maven
3.9.2is used. If you use an earlier version of Maven, upgrade the Maven version and try again.
After you install the
EncDB SDKdependency package in your on-premises repository, add the following dependencies to the pom.xml configuration file of your Maven project:<dependencies> ... <dependency> <groupId>com.alibaba.encdb</groupId> <artifactId>libencdb</artifactId> <version>1.2.12</version> </dependency> <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.70</version> </dependency> <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk15on</artifactId> <version>1.70</version> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.10.1</version> </dependency> <!-- https://mvnrepository.com/artifact/org.postgresql/postgresql --> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>42.2.23</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>31.1-jre</version> </dependency> ... </dependencies>
Query data from the client (sample code)
The sample code in this section is for demonstration only. In the actual business code, do not set the password and mek parameters to values in plaintext. We recommend that you configure the parameters by using methods such as external configuration files and environment variables before you reference the parameters in the code.
SDK configuration description
Before you manage ciphertext data that you receive or send, you must use the
EncDB SDKto encrypt or decrypt the data.The
EncDB SDKprovides the required API operations for configuring parameters related to data security when you initialize SDK objects. In most cases, you need to only configure the MEK specified by the setMek parameter and the required encryption algorithm specified by the setEncAlgo parameter. We recommend that you use the default settings for other parameters.// Obtain the connection information including the domain name (hostname), port number (port), database name (dbname), username (username), and password (password). // Establish a database connection. All JDBC versions are supported. String dbUrl = String.format("jdbc:postgresql://%s:%s/%s?binaryTransfer=true", hostname, port, dbname); Class.forName("org.postgresql.Driver"); Connection dbConnection = DriverManager.getConnection(dbUrl, username, password); // Initialize the SDK. String mek=...; Constants.EncAlgo encAlgo=...; EncdbSDK sdk = EncdbSDKBuilder.newInstance() .setDbConnection(connection) .setMek(mek) .setEncAlgo(encAlgo) .build(); Cryptor cryptor = sdk.getCryptor(); // Invoke the API operation for data encryption or decryption. // byte[] cipherBytes = cryptor.encrypt(...); // XXX value = cryptor.decryptXXX(...): // ... Initiate a query ...NoteThe
mekparameter and other parameters are configured on the client side and transmitted to the server side by using envelope encryption. In the process, the confidentiality of themekvalue is ensured.Complete sample code
// The connection information of your cluster, including the domain name (hostname), port number (port), database name (dbname), username (username), and password (password). String hostname = "hostname"; String port = "port"; String dbname = "db"; String username = "user"; String password = "password"; // Establish a database connection. String dbUrl = String.format("jdbc:postgresql://%s:%s/%s?binaryTransfer=true", hostname, port, dbname); Class.forName("org.postgresql.Driver"); Connection dbConnection = DriverManager.getConnection(dbUrl, username, password); // Initialize the SDK. String mek="00112233445566778899aabbccddeeff"; // This is an example value. We recommend that you use a more complex MEK. Constants.EncAlgo encAlgo=Constants.EncAlgo.SM4_128_CBC; EncdbSDK sdk = EncdbSDKBuilder.newInstance() .setDbConnection(connection) .setMek(mek) .setEncAlgo(encAlgo) .build(); Cryptor cryptor = sdk.getCryptor(); // create table dbConnection.createStatement().executeUpdate("DROP TABLE IF EXISTS example"); dbConnection.createStatement().executeUpdate("CREATE TABLE example (id INTEGER, name VARCHAR, price enc_int4, miles enc_float4, secret enc_text, PRIMARY KEY (id))"); // insert data PreparedStatement stmt = dbConnection.prepareStatement("INSERT INTO example (id, name, price, miles, secret) VALUES(?,?,?,?,?)"); int price = 1234; float miles = 12.34f; String secret = "aliyun"; stmt.setInt(1, 1); stmt.setString(2, "name"); stmt.setBytes(3, cryptor.encrypt("example", "price", price)); stmt.setBytes(4, cryptor.encrypt("example", "miles", miles)); stmt.setBytes(5, cryptor.encrypt("example", "secret", secret)); stmt.execute(); // check plaintext data String sqlCmd = "SELECT * FROM example WHERE price > ?"; PreparedStatement stmt = dbConnection.prepareStatement(sqlCmd); stmt.setBytes(1, cryptor.encrypt("example", "price", 100)); ResultSet rs = stmt.executeQuery(); while (rs.next()) { int id = rs.getInt(1); String name = rs.getString(2); int price = cryptor.decryptInt(rs.getBytes(3)); float miles = cryptor.decryptFloat(rs.getBytes(4)); String text = cryptor.decryptString(rs.getBytes(5)); System.out.println(id +", " + name + ", " + price + ", " + miles + ", " + text); }Sample output:
1, name, 1234, 12.34, aliyun
References
Introduction to the Java SDK module
The EncDB SDK contains the following Java feature modules:
psql
You can use psql to query data in confidential databases. For example, you can execute the SELECT * FROM example; statement by using psql.

In the preceding output, id and name are plaintext columns, and price, miles, and secret are ciphertext columns. Encrypted data cannot be viewed on the PolarDB for PostgreSQL cluster. This helps protect your data from security threats inside and outside the cloud at all times.
DMS console
You can use visual and interactive tools such as the DMS console to query data in confidential databases.

In the preceding figure, id and name are plaintext columns, and price, miles, and secret are ciphertext columns.
FAQ
What do I do if the error message org.postgresql.util.PSQLException: ERROR: db_process_msg_api: process message failure - returned 0xf7070000 is displayed when I connect to my database?
The error code 0xf7070000 indicates that your MEK cannot be imported. The data that is encrypted by using one MEK cannot be accessed by using another MEK. If you use the same account but different MEKs to connect to the same always-confidential database, this error may occur. We recommend that you use the same MEK to connect to a always-confidential database.