If you want to use the always-confidential feature to encrypt data of specific data columns in a database table and use a Java application to connect to the database, you can use EncDB SDK. This facilitates database connection and simplifies the usage of the always-confidential feature. This topic describes how to connect to an always-confidential database by using EncDB SDK.
EncDB SDK supports trusted key management, end-to-end secure communication, and data encryption and decryption, and provides API operations that you can use from your applications to control the process of data encryption based on your business requirements.
Prerequisites
The always-confidential feature is enabled. For more information, see Enable the always-confidential feature.
The connection information about the RDS instance for which the always-confidential feature is enabled is obtained. The connection information includes the domain name (host), port number (port), instance name (dbname), username (username), and password (password).
A data protection rule is configured. For more information, see Configure data protection rules.
Usage notes
You must store your
master encryption key (MEK)and keep it confidential.JDK 1.8 or later is used.
NoteIn this topic, the version of Maven is
3.9.2, and the development tool isIntelliJ IDEA Community Edition 2022.3.2.
Procedure
Download the EncDB SDK JAR package and add dependencies
EncDB SDK JAR package
EncDB SDK supports all MySQL-compatible clients, such as MySQL JDBC. For more information, see MySQL Connector. You can click libencdb-1.2.13-SNAPSHOT.jar to download the EncDB SDK JAR package.
Add Maven dependencies
If your Java project is built by using Maven, run the following command to install the preceding
EncJDBCJAR package to your local 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=libencdb -Dversion=1.2.13-SNAPSHOT -Dpackaging=jar -Dfile=libencdb-1.2.13-SNAPSHOT.jarAfter you install the
EncDB SDKJAR package, add the following dependencies to the configuration file of your project in Maven.<dependencies> ... <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>Required version of the MySQL JDBC driver from 8.0.11 to 8.0.32</version> </dependency> <dependency> <groupId>com.alibaba.encdb</groupId> <artifactId>libencdb</artifactId> <version>1.2.13-SNAPSHOT</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.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.10.1</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>24.1.1-jre</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.30</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.30</version> </dependency> ... </dependencies>
Configure EncDB SDK based on sample code
Before you manage ciphertext data that you receive or send, you must use EncDB SDK to encrypt or decrypt the data. Before you use EncDB SDK, you must configure data security-related parameters, such as MEK, EncAlgo, and KeyMgmtType, in EncDB SDK. MEK specifies the master encryption key, EncAlgo specifies the encryption algorithm, and KeyMgmtType specifies the key management type.
The following table describes the parameters and provides example values.
Parameter | Example (string type) | Description |
MEK | 00112233445566778899aabbccddeeff | The MEK that is specified by the data owner. MEK generation: You can use password generation tools such as OpenSSL and openssl rand -hex 16, call the random function in a programming language, or obtain keys from Key Management Service (KMS). Valid value: a 16-byte hexadecimal string that is 32 characters in length. Warning An MEK is the root credential that you use to access encrypted data. For security purposes, the RDS instance for which the always-confidential feature is enabled does not generate, store, or back up your MEK. You must generate an MEK and keep it confidential. If you lose your MEK, you can no longer access the data that is encrypted by using the MEK. We recommend that you back up your MEK. |
EncAlgo | SM4_128_GCM | The encryption algorithms that are used to protect the data. Valid values:
Note
|
KeyMgmtType | RDS_MYSQL | The key management type that is used for the always-confidential feature. The value is fixed for the specified types of databases. Valid values:
|
SDK configuration
EncDB SDK provides API operations that are used to configure parameters for the initialization of SDK objects. In most cases, you need to configure only the setMek and setEncAlgo parameters. setMek specifies the MEK and setEncAlgo specifies the required encryption algorithm. For other parameters, we recommend that you use the default values or fixed values.
// Obtain the connection information such as the domain name (hostname), port number (port), instance name (dbname), username (username), and password (password).
// ...
// Use MySQL JDBC to connect to the instance.
Class.forName("com.mysql.cj.jdbc.Driver");
String dbUrl = String.format("jdbc:mysql://%s:%s/%s", hostname, port, dbname);
Connection connection = DriverManager.getConnection(dbUrl, username, password);
// Initialize the MEK and obtain the encryption and decryption operator.
String mek = "00112233445566778899aabbccddeeff";
Constants.EncAlgo encAlgo=Constants.EncAlgo.SM4_128_CBC;
Constants.KeyMgmtType keyMgmtType=Constants.KeyMgmtType.RDS_MYSQL;
EncdbSDK sdk = EncdbSDKBuilder.newInstance()
.setKeyMgmtType(keyMgmtType)
.setDbConnection(connection)
.setMek(mek)
.setEncAlgo(encAlgo)
.build();
Cryptor cryptor = sdk.getCryptor();
// Call the API operation for data encryption or decryption.
// byte[] cipherBytes = cryptor.encrypt(...);
// XXX value = cryptor.decryptXXX(...):
// ... Initiate a query ...The mek parameter and other parameters are configured on the client side and transmitted to the server by using envelope encryption. During the process, the confidentiality of the value of the mek parameter is ensured.
Complete sample code
The following sample code is compiled based on MySQL JDBC and EncDB SDK. You must add MySQL JDBC as a dependency in Maven and configure the enc_int column as a protected column.
// Update the connection information such as the domain name (hostname), port number (port), instance name (dbname), username (username), and password (password) to your instance information.
String hostname = "hostname";
String port = "port";
String dbname = "db";
String username = "user";
String password = "password";
// Use MySQL JDBC to connect to the instance.
Class.forName("com.mysql.cj.jdbc.Driver");
String dbUrl = String.format("jdbc:mysql://%s:%s/%s", hostname, port, dbname);
Connection connection = DriverManager.getConnection(dbUrl, username, password);
// Initialize the MEK and obtain the encryption and decryption operator.
String mek = "00112233445566778899aabbccddeeff";
Constants.EncAlgo encAlgo=Constants.EncAlgo.SM4_128_CBC;
Constants.KeyMgmtType keyMgmtType=Constants.KeyMgmtType.RDS_MYSQL;
EncdbSDK sdk = EncdbSDKBuilder.newInstance()
.setKeyMgmtType(keyMgmtType)
.setDbConnection(connection)
.setMek(mek)
.setEncAlgo(encAlgo)
.build();
Cryptor cryptor = sdk.getCryptor();
// Create a table and write data to it.
connection.createStatement().executeUpdate("drop table if exists test");
connection.createStatement().executeUpdate("create table test (enc_int int)");
connection.createStatement().executeUpdate("insert into test values (1)");
// Initiate a query.
ResultSet rs = connection.createStatement().executeQuery("select * from test");
while (rs.next()) {
for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {
// Obtain the ciphertext.
byte[] cipher = rs.getBytes(i + 1);
// Call the Cryptor.decrypt method to decrypt the ciphertext.
byte[] plaintext = cryptor.decrypt(Base64.decode(new String(cipher, StandardCharsets.UTF_8)));
// Returns the ciphertext and plaintext.
System.out.println("Plaintext:" + new String(plaintext) + ",Ciphertext:" + new String(cipher));
}
System.out.print("\n");
}Output:
Plaintext: 1 Ciphertext: QmEA/4d0ROXfA3QeUZFiu7EdlvZy4Yaa+uDnyFHvFOnVK4dtgVIzjrYI54I=Related operations
EncDB SDK contains the following Java feature modules:
FAQ
What do I do if the
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 @0x5c0369c4error message is displayed when I run a program?The error message may be displayed due to the inter-module permission issues that occur when the JDK version is later than the required version. To resolve the error, you must add the VM option
--add-exports=java.base/com.sun.crypto.provider=ALL-UNNAMEDwhen you run the program to export com.sun.crypto.provider to the Unnamed module.What do I do if the
failed in mek provision: you might have an incorrect mek setting. Detail:gcmEncrypt errorerror message is displayed when I run a program?The error is a common error in Oracle JDK. To resolve the error, you can use one of the following methods:
Use Amazon Corretto instead.
If you use Oracle JDK, you must perform the following steps to configure a security provider:
Find the JDK installation path.
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 content:security.provider.14=org.bouncycastle.jce.provider.BouncyCastleProvider