To access data in columns protected by column encryption from a Java application, you can use the EncJDBC driver to connect to your database. This driver provides a convenient and cost-effective way to work with encrypted data. This topic shows how to use EncJDBC to retrieve plaintext from encrypted database columns.
When you provide the master encryption key, the data transmission link is fully encrypted. The EncJDBC client automatically decrypts and returns plaintext, which your application can then display with only minor configuration.
Prerequisites
-
You have run a sensitive data detection scan to find columns that require encryption.
-
You have configured column encryption for the target database and set the permission for the database account to Ciphertext Permission (JDBC Decryption). For detailed instructions, see column encryption.
You have the connection details for the encrypted database, including the hostname, port, database name, username, and password.
Generate an MEK
-
Value range: A 16-byte hexadecimal string, which is 32 characters long.
Based on the key type you selected when you configured column encryption, you can use either a KMS Key or generate a local key as your MEK to decrypt the database.
KMS key
When you use a KMS key, ensure that Key Management Service (KMS) is available. Otherwise, the always-encrypted client driver EncJDBC will not function.
You need to obtain the endpoint of the KMS instance that contains the selected KMS key from the column encryption configuration. You also need the AccessKey ID and AccessKey secret of the corresponding Alibaba Cloud account or Resource Access Management (RAM) user. This account or user must have KMS decryption permissions to allow the client to read the KMS key. Perform the following steps:
Log on to the console using an Alibaba Cloud account or a RAM user.
Local key
When the Encryption Method in the column encryption configuration is set to Local Key, you need to generate an MEK. For example, 00112233445566778899aabbccddeeff.
Common generation methods include using a password generation tool or a random function in a programming language.
For example:
On Linux, you can use the built-in OpenSSL tool and run the
openssl rand -hex 16command to generate a key.On Windows, you can install the OpenSSL software package.
Client access instructions
Use Java Development Kit (JDK) 1.8 or later.
On the client, you can change the database connection driver to EncJDBC, update the database connection URL, and specify the MEK to access the plaintext data in encrypted columns.
1. 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>2. Configure the MEK to connect to the database
You can use the following methods to configure the MEK: JDBC properties configuration, file configuration, and URL configuration. If you configure your Java Database Connectivity (JDBC) using more than one method, the following priority applies: JDBC properties configuration > File configuration > URL configuration.
In the URL configuration method, you can concatenate multiple parameters with an ampersand (
&).With the following configuration and connection methods, the
MEKis processed locally on the client and sent to the server securely using envelope encryption. This ensures that theMEKis not leaked.
Based on the Encryption Method in the column encryption configuration, connect to the database using either a local key or a KMS key.
Connect to the database using a KMS key
If you use a temporary access credential from the Security Token Service (STS) to obtain the KMS-managed MEK, you can use an STS software development kit (SDK) to obtain a temporary STS token. For STS SDK examples, see STS SDK overview.
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.
JDBC properties configuration
When you connect using standard JDBC, you can set custom user properties through Properties. The following example shows how to configure and run JDBC in this way:
// Prepare the 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 system environment variables.
String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
// If you use an STS temporary access credential to read the KMS key, you also need to provide the obtained Security Token Service (STS) token.
// String stsToken= "yourSecurityToken";
// The endpoint of the KMS instance. Use the public endpoint for Internet access. Use the instance VPC endpoint for VPC access.
String kmsEndpoint = "kms.cn-hangzhou.aliyuncs.com";
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 an RDS for 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 an RDS for 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, as shown in the following example:
// Prepare the 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 system environment variables.
String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
// If you use an STS temporary access credential to read the KMS key, you also need to provide the obtained STS token.
// String stsToken= "yourSecurityToken";
// The endpoint of the KMS instance. Use the public endpoint for Internet access. Use the instance VPC endpoint for VPC access.
String kmsEndpoint = "kms.cn-hangzhou.aliyuncs.com";
// The following is the connection URL format for an RDS for 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 an RDS for MySQL database.
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
// Get the database connection.
Connection connection = DriverManager.getConnection(dbUrl, username, password);
// ... Initiate a query ...Connect to the database using a local key
JDBC properties configuration
When you connect using standard JDBC, you can set custom user properties through Properties. The following example shows how to configure and run JDBC in this way:
// Prepare the 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 following is the connection URL format for an RDS for MySQL database: "jdbc:mysql:encdb://%s:%s/%s". For an RDS for PostgreSQL database, replace the format with "jdbc:postgresql:encdb://%s:%s/%s".
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);
// The following loads the EncJDBC driver for an RDS for MySQL database. For an RDS for PostgreSQL database, replace the driver with "com.aliyun.encdb.postgresql.jdbc.EncDriver".
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
// Get the database connection.
Connection connection = DriverManager.getConnection(dbUrl, props);
// ... Initiate a query ...File configuration
You can import parameters, such as the required MEK, from a configuration file.
The file configuration method is applicable only to configuring a local key MEK.
In your project, you can set a property named encJdbcConfigFile and set its value to the path of the configuration file. If you do not set this property, the encjdbc.conf file is used by default. The content of the configuration file is as follows:
MEK=00112233445566778899aabbccddeeffYou can place the configuration file in one of the following two locations:
Place the file in the resources folder of your project, as shown in the following figure:

Place the file in the project root directory, which is the runtime directory of the program.
After you configure the file, you do not need to make additional configurations in your program, as shown in the following example:
// Prepare the 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 following is the connection URL format for an RDS for MySQL database: "jdbc:mysql:encdb://%s:%s/%s". For an RDS for PostgreSQL database, replace the format with "jdbc:postgresql:encdb://%s:%s/%s".
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);
// The following loads the EncJDBC driver for an RDS for MySQL database. For an RDS for PostgreSQL database, replace the driver with "com.aliyun.encdb.postgresql.jdbc.EncDriver".
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 parameters, such as the MEK, in the URL, as shown in the following example:
// Prepare the 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 following is the connection URL format for an RDS for MySQL database: "jdbc:mysql:encdb://%s:%s/%s?MEK=%s". For an RDS for PostgreSQL database, replace the format with "jdbc:postgresql:encdb://%s:%s/%s?MEK=%s".
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s?MEK=%s", hostname, port, dbname, mek);
// The following loads the EncJDBC driver for an RDS for MySQL database. For an RDS for PostgreSQL database, replace the driver with "com.aliyun.encdb.postgresql.jdbc.EncDriver".
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
// Get the database connection.
Connection connection = DriverManager.getConnection(dbUrl, username, password);
// ... Initiate a query ...3. Query the plaintext data of encrypted columns
After you successfully connect to the database, you can perform database operations as you would with a normal JDBC query. EncJDBC automatically decrypts the encrypted columns and returns plaintext data.
Sample code:
// Initiate a query.
// 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 < resultSet.getMetaData().getColumnCount(); i++) {
System.out.print(resultSet.getString(i + 1));
System.out.print("\t");
}
System.out.print("\n");
}FAQ
Q: When I run the program, I get the following error:
Exception in thread "main" java.lang.IllegalAccessError: class com.alibaba.encdb.common.SymCrypto (in unnamed module @0x5c0369c4) cannot access class com.sun.crypto.provider.SunJCE (in module java.base) because module java.base does not export com.sun.crypto.provider to unnamed module @0x5c0369c4. How do I fix this?A: This error can occur in recent JDK versions due to module access restrictions. Add the VM option
--add-exports=java.base/com.sun.crypto.provider=ALL-UNNAMEDat runtime to export the com.sun.crypto.provider package to the unnamed module.Q: When I run the program, I get the following error:
failed in mek provision: you might have an incorrect mek setting. Detail:gcmEncrypt error. How do I fix it?A: This issue is common with Oracle JDK. To resolve this, use one of the following methods:
Use an Amazon Corretto JDK.
Continue to use an Oracle JDK, but manually configure the security provider. Follow these steps:
Find the JDK installation directory.
In the
<installation_path>/conf/security/directory, find thejava.securityfile.Edit the
java.securityfile. In theList of providers and their preference orders (see above):section, add the following line:security.provider.14=org.bouncycastle.jce.provider.BouncyCastleProvider