All Products
Search
Document Center

ApsaraDB RDS:EncDB SDK

Last Updated:Feb 29, 2024

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.

    Note

    In this topic, the version of Maven is 3.9.2, and the development tool is IntelliJ 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

  1. If your Java project is built by using Maven, run the following command to install the preceding EncJDBC JAR 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.jar
  2. After you install the EncDB SDK JAR 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:

  • Internationally accepted algorithms:

    • AES_128_GCM

    • AES_128_CTR

    • AES_128_CBC

    • AES_128_ECB (not recommended)

  • SM algorithms:

    • SM4_128_GCM (default)

    • SM4_128_CTR

    • SM4_128_CBC

    • SM4_128_ECB (not recommended)

Note
  • The AES_128_ECB and SM4_128_ECB encryption algorithms cannot provide high security. We recommend that you select other encryption algorithms that provide higher security than the AES_128_ECB and SM4_128_ECB encryption algorithms.

  • Optional. The default value is SM4_128_GCM.

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:

  • RDS_MYSQL: applies to ApsaraDB RDS for MySQL instances.

  • POLARDB_MYSQL: applies to PolarDB for MySQL clusters when they are connected by using a database proxy.

  • PG: applies to ApsaraDB RDS for PostgreSQL instances and PolarDB for PostgreSQL clusters.

  • KEYSTORE_SERVER: applies to a service-oriented encrypted metadata management system, such as KeyStore.

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 ...
Note

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:

com.alibaba.encdb.crypto.EncdbSDKBuilder

This module is a constructed class of the EncDB SDK class.

// Obtain a new EncdbSDKBuilder instance. You must use this method to construct EncdbSDKBuilder. 
EncdbSDKBuilder newInstance();
// Required. Specify the database connection for key management. The configured database connection is different from the database connection that is used in actual business scenarios. 
EncdbSDKBuilder setDbConnection(java.sql.Connection dbConnection);
// Required. Specify the key management type.
EncdbSDKBuilder setKeyMgmtType(KeyMgmtType kmType);
// Required. Specify the MEK.
EncdbSDKBuilder setMek(byte[] mek);
EncdbSDKBuilder setMek(String mek);
/ Optional. Specify the encryption algorithm.
EncdbSDKBuilder setEncAlgo(EncAlgo encAlgo);
// After the preceding configurations are complete, construct an EncdbSDK object.
EncdbSDK build();

com.alibaba.encdb.EncdbSDK

This module provides capabilities such as trusted key management and end-to-end secure communication.

// Obtain a Cryptor object to perform operations on ciphertext and plaintext data. 
Cryptor getCryptor();

com.alibaba.encdb.Cryptor

This module provides cryptographic computing capabilities.

// Pass in the ciphertext and obtain the corresponding plaintext. You need to convert the plaintext to the required data type. 
byte[] decrypt(byte[] val);

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 @0x5c0369c4 error 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-UNNAMED when 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 error error 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:

      1. Find the JDK installation path.

      2. In the Installation path/conf/security/ directory, find the java.security file.

      3. Edit the java.security file. In the List of providers and their preference orders (see above): section, add the following content:

        security.provider.14=org.bouncycastle.jce.provider.BouncyCastleProvider