配置步骤(非安全增强型实例)

更新时间: 2023-09-06 14:59:02

本文介绍如何在非Intel SGX 增强型实例中配置和使用全加密云数据库功能。

前提条件

  • RDS PostgreSQL服务端

  • 本地客户端

    • 本文示例代码使用的开发语言为Java,请确保已具备Java开发环境,建议使用Java版本为1.8及以上,使用的开发工具为IntelliJ IDEA Community Edition 2022.3.2

    • 已根据服务端版本下载对应EncDB依赖包。

      RDS PostgreSQL小版本

      服务端encdb插件版本号

      客户端EncDB依赖包

      20210531

      1.1.5

      libencdb-1.2.1.jar

      20210930

      1.1.6

      libencdb-1.2.4.jar

      20211031 ~ 20220130

      1.1.7

      libencdb-1.2.5.jar

      20220228 ~ 20220730

      1.1.9

      libencdb-1.2.6.jar

      20220830 ~ 20221030

      说明

      RDS PostgreSQL 15在20221030内核版本时,配套插件版本为1.1.12。

      1.1.11

      libencdb-1.2.8.jar

      20221230或以上版本

      1.1.12

      libencdb-1.2.12.jar

    • 已生成用户主密钥。

      用户主密钥由长度为16字节的16进制字符串组成,本示例以0x00112233445566778899aabbccddeeff为例。常见的生成方法有:密码生成工具(如openssl, openssl rand -hex 16)、编程语言中的random函数。

      警告

      用户主密钥是您访问加密数据的根凭据,全加密功能不提供用户主密钥的生成和备份服务,您需要自行生成用户主密钥。一旦您丢失密钥,将无法再访问已有的数据。因此我们建议您妥善备份用户主密钥。

背景信息

在RDS PostgreSQL的非Intel SGX 安全增强型规格实例上,全加密功能可以利用密码学方法提供数据安全保护,但支持的操作类型较少,具体请参见功能支持

说明

RDS PostgreSQL 10或其以上版本的所有实例规格都支持全加密功能,但推荐您选择Intel SGX 安全增强型规格,以获得最完整的全加密功能支持。安全增强型规格的配置步骤,请参见配置步骤(安全增强型实例)

本文以非Intel SGX 安全增强型规格的PostgreSQL实例为例,介绍如何通过客户端连接并使用全加密云数据库。

服务端配置步骤

全加密云数据库在RDS PostgreSQL服务端以扩展(Extension)形式部署。本步骤介绍如何在服务器端安装扩展以及创建加密表。

说明

本步骤需要连接RDS PostgreSQL实例进行操作,连接方法请参见连接PostgreSQL实例

  1. 安装EncDB扩展。

    CREATE EXTENSION encdb;
  2. 创建加密表。

    创建加密表时,您可以根据自身需要,将敏感字段的数据类型替换为对应的加密数据类型。以下表为例,其原始定义如下:

    CREATE TABLE example (
      id      INTEGER,
      name    VARCHAR,
      price   INTEGER,
      miles   REAL,
      secret  TEXT,
      PRIMARY KEY (id)
    );

    如果选择price,miles,secret为敏感数据,创建的加密表定义如下:

    CREATE TABLE example (
      id     INTEGER,
      name   VARCHAR,
      price  rnd_type,
      miles  det_type,
      secret rnd_type,
      PRIMARY KEY (id)
    );
    说明
    • 非Intel SGX 增强型实例中,全加密数据库功能目前支持det_typernd_type两种加密数据类型。其中det_type为确定性加密(同一个敏感数据两次加密得到的密文相同),rnd_type为不确定性加密 (同一个敏感数据两次加密得到的密文不同)。

    • 当您在应用程序中使用det_typernd_type时,需要将全加密数据库det_type和rnd_type对应的宿主变量转换为string数据类型。

    • 您不能直接修改原有表(即ALTER TABLE),而是需要新建一个加密表,然后再将原表数据通过SDK加密后导入。

客户端配置步骤

本步骤介绍客户端如何连接数据库并进行数据加密解密操作。

说明

本示例以Maven构建Java项目为例。

  1. 安装EncDB依赖包。

    mvn install:install-file -DgroupId=com.alibaba.encdb -DartifactId=<安装的Jar包名> -Dversion=<安装的Jar版本> -Dpackaging=jar -Dfile=<下载的Jar包所在路径>/<安装的Jar包名.jar>

    示例:

    mvn install:install-file -DgroupId=com.alibaba.encdb -DartifactId=libencdb -Dversion=1.2.12 -Dpackaging=jar -Dfile=D:\encdb\libs\libencdb-1.2.12.jar
    说明
    • 此示例中EncDB依赖包在D:\encdb\libs路径下。

    • 此示例使用的Maven版本为3.9.2,如果您安装报错,请升级Maven版本后再试。

  2. 添加依赖。

    您需要在pom.xml中添加如下依赖:

    <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>
  3. 全加密功能使用示例。

    1. 连接数据库。

      说明

      此示例中MEK仅为测试用,实际应用中请使用自己的MEK。参数MekEncAlgo只作为EncDB SDK的加解密模块使用,不会直接传送给服务器端。

       try {
          Class.forName("org.postgresql.Driver");
      } catch (ClassNotFoundException e) {
          e.printStackTrace();
      }
      
       String hostname = "pgm-uf6qw1ap115gr2****.pg.rds.aliyuncs.com";
       String port = "5432";
       String dbname = "encdbtest";
       String username = "username";
       String password = "userpassword";
       String tableName = "example";
       String mek = "0x00112233445566778899aabbccddeeff";
      
       String dbUrl = "jdbc:postgresql://" + hostname + ":" + port + "/" + dbname + "?binaryTransfer=true";
       try {
          dbConnection = DriverManager.getConnection(dbUrl, username, password);
      } catch (SQLException throwables) {
          throwables.printStackTrace();
      }
      
       /*创建EncdbSDK实例*/
       EncdbSDK sdk = EncdbSDKBuilder.newInstance()
               .setDbConnection(dbConnection)
               .setMek(mek)
               .setEncAlgo(Constants.EncAlgo.SM4_128_CBC)
               .setDekGenMode(Constants.DekGenMode.LOCAL)
               .setSdkMode(Constants.SDKMode.Crypto)
               .build();
      
       Cryptor crypto = sdk.getCryptor();

      上述示例中关键参数解释及取值示例如下:

      参数

      取值示例(字符串类型)

      说明

      Mek

      0x00112233445566778899aabbccddeeff

      用户主密钥。

      取值范围:长度为16字节的16进制字符串。

      EncAlgo

      SM4_128_CBC

      加密算法。

      取值范围:

      • AES_128_GCM

      • AES_128_CBC

      • SM4_128_CBC(默认值)

      DekGenMode

      LOCAL

      生成数据密钥的方式。固定为LOCAL,不能修改。

      SdkMode

      Crypto

      SDK模式。固定为Crypto,不能修改。

    2. 插入加密数据。

       PreparedStatement stmt = dbConnection.prepareStatement("insert into " + tableName + " (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, crypto.encrypt(tableName, "price", String.valueOf(price)));
       stmt.setBytes(4, crypto.encrypt(tableName, "miles", String.valueOf(miles)));
       stmt.setBytes(5, crypto.encrypt(tableName, "secret", secret));
       stmt.execute();
    3. 查询解密数据。

       String sqlCmd = "SELECT * from " + tableName + " where miles = ?";
       PreparedStatement stmt = dbConnection.prepareStatement(sqlCmd);
       stmt.setBytes(1, crypto.encrypt(tableName, "miles", "12.34"));
       ResultSet rs = stmt.executeQuery();
       while (rs.next()) {
           int id = rs.getInt(1);
           String name = rs.getString(2);
      
           int price = Integer.parseInt(crypto.decryptString(rs.getBytes(3)));
           float miles = Float.parseFloat(crypto.decryptString(rs.getBytes(4)));
           String text = crypto.decryptString(rs.getBytes(5));
      
           System.out.println(id + ", " + name + ", " + price + ", " + miles + ", " + text);
       }

    查询结果:

    • 已加密的数据在客户端查询时被解密,您可以查询到明文。

      1, name, 1234, 12.34, aliyun
    • 已被加密的数据在服务器端无法查看,能够有效防御来自云平台外部和内部的安全威胁,时刻保护用户数据。

      select * from example;
       id | name |                                  price                                   |                                  miles                                   |                                  secret
      ----+------+--------------------------------------------------------------------------+--------------------------------------------------------------------------+--------------------------------------------------------------------------
        1 | name | \xdf4901df087c6a3e0325175bb76942c684191a8dda2a8d0c35f295dc1e30eaeaa0c0e3 | \x315102ea5ab8a659066ab672e6dfbfd89a3a2b360bf6efe3787931e00f61af05f7408c | \xed4903dfd1bda1a89ad6aa7e8905c0e6305e15db4bc9ce2d2cfac9e25094d2a3ed367d
      (1 行记录)
阿里云首页 云数据库 RDS 相关技术圈