全密态数据库

全密态数据库意在解决数据全生命周期的隐私保护问题,使得系统无论在何种业务场景和环境下,数据在传输、运算以及存储的各个环节始终都处于密文状态。当数据拥有者在客户端完成数据加密并发送给服务端后,在攻击者借助系统脆弱点窃取用户数据的状态下仍然无法获得有效的价值信息,从而起到保护数据隐私的能力。

由于整个业务数据流在数据处理过程中都是以密文形态存在,通过全密态数据库,可以实现:

  • 保护数据在云上全生命周期的隐私安全。无论数据处于何种状态,攻击者都无法从数据库服务端获取有效信息。
  • 帮助云服务提供商获取第三方信任。无论是企业服务场景下的业务管理员、运维管理员,还是消费者云业务下的应用开发者,用户通过将密钥掌握在自己手上,使得高权限用户无法获取数据有效信息。
  • 让云数据库服务借助全密态能力更好的遵守个人隐私保护方面的法律法规。

全密态数据库目前支持两种连接方式:gsql连接和jdbc连接。下面将详细介绍两种连接方式下数据库的使用流程。

连接全密态数据库

  • GSQL连接数据库执行以下命令打开密态开关:

    1. gsql -p PORT -d postgres -r -C

    参数说明:

    • -p:端口号
    • -d:数据库名称
    • -C:是打开密态开关。
  • JDBC支持密态数据库相关操作,需要设置enable_ce=1

创建用户密钥

全密态数据库有两种密钥,即客户端主密钥CMK和数据加密密钥CEK。CMK用于加密CEK,CEK用于加密用户数据。

密钥创建的顺序和依赖依次为: 创建CMK > 创建CEK。

  • GSQL环境下创建CMK和CEK:

    【创建CMK】

    1. CREATE CLIENT MASTER KEY client_master_key_name WITH KEY_STORE =key_store_name, KEY_PATH = "key_path_value", ALGORITHM = algorithm_type);

    参数说明:

    • client_master_key_name

      该参数作为密钥对象名,在同一命名空间下,需满足命名唯一性约束。

      取值范围:字符串,需符合标识符的命名规范。

    • KEY_STORE

      指定管理CMK的密钥工具或组件;取值:目前仅支持localkms。

    • KEY_PATH

      KEY_STORE负责管理多个CMK密钥,KEY_PATH选项用于在KEY_STORE中唯一标识CMK。取值类似:“key_path_value”。

    • ALGORITHM

      由本语法创建的用于加密COLUMN ENCRYPTION KEY,该参数用于指定加密算法的类型。取值范围:RSA_2048、RSA3072和SM2。

    全密态数据库 - 图1 说明: 密钥存储路径:默认情况下,localkms将在$LOCALKMS_FILE_PATH路径下生成/读取/删除密钥文件,用户可手动配置该环境变量。但是,用户也可以不用单独配置该环境变量,在尝试获取$LOCALKMS_FILE_PATH失败时,localkms会尝试获取$GAUSSHOME/etc/localkms/路径,如果该路径存在,则将其作为密钥存储路径。 密钥相关文件名:使用CREATE CMK语法时,localkms将会创建四个与存储密钥相关的文件。示例:当KEY_PATH = “key_path_value”, 四个文件的名称分别为key_path_value.pub、key_path_value.pub.rand、 key_path_value.priv、 key_path_value.priv.rand。 所以,为了能够成功创建密钥相关文件,在密钥存储路径下,应该保证没有已存在的与密钥相关文件名同名的文件。

    【创建CEK】

    1. CREATE COLUMN ENCRYPTION KEY column_encryption_key_name WITH(CLIENT_MASTER_KEY = client_master_key_name, ALGORITHM = algorithm_type, ENCRYPTED_VALUE = encrypted_value);

    参数说明:

    • column_encryption_key_name

      该参数作为密钥对象名,在同一命名空间下,需满足命名唯一性约束。

      取值范围:字符串,要符合标识符的命名规范。

    • CLIENT_MASTER_KEY

      指定用于加密本CEK的CMK。

      取值为:CMK对象名,该CMK对象由CREATE CLIENT MASTER KEY语法创建。

    • ALGORITHM

      指定该CEK将用于何种加密算法。

      取值范围为:AEAD_AES_256_CBC_HMAC_SHA256、AEAD_AES_128_CBC_HMAC_SHA256和SM4_SM3;

    • ENCRYPTED_VALUE(可选项)

      该值为用户指定的密钥口令,密钥口令长度范围为28 ~ 256个字符。28个字符派生出来的密钥安全强度满足AES128。若用户需要用AES256,密钥口令的长度需要39个字符。如果不指定,则会自动生成256比特的密钥。

    全密态数据库 - 图2 说明: 由于SM2、SM3、SM4等算法属于中国国家密码标准算法,为规避法律风险,需配套使用。如果创建CMK时指定SM4算法来加密CEK,则创建CEK时必须指定SM4_SM3算法来加密数据。

    【示例:GSQL环境下:】

    1. -- 创建$GAUSSHOME/etc/localkms/路径
    2. mkdir -p $GAUSSHOME/etc/localkms/
    3. -- 使用特权账户,创建一个普通用户alice
    4. openGauss=# CREATE USER alice PASSWORD '********';
    5. -- 使用普通用户alice的账户,连接密态数据库,并执行本语法。
    6. gsql -p 57101 postgres -U alice -r -C
    7. -- 创建客户端加密主密钥(CMK)对象。
    8. openGauss=> CREATE CLIENT MASTER KEY alice_cmk WITH (KEY_STORE = localkms , KEY_PATH = "key_path_value”, ALGORITHM = RSA_2048);
    9. -- 创建客户端列加密密钥(CEK)对象。
    10. openGauss=> CREATE COLUMN ENCRYPTION KEY ImgCEK WITH VALUES (CLIENT_MASTER_KEY = alice_cmk, ALGORITHM = AEAD_AES_256_CBC_HMAC_SHA256);
  • JDBC环境下创建CMK和CEK:

    1. // 创建客户端主密钥
    2. Connection conn = DriverManager.getConnection("url","user","password");Statement stmt = conn.createStatement();int rc = stmt.executeUpdate("CREATE CLIENT MASTER KEY ImgCMK1 WITH ( KEY_STORE = localkms , KEY_PATH = "key_path_value" , ALGORITHM = AES_256_CBC);");
    3. // 创建列加密密钥
    4. int rc2 = stmt.executeUpdate("CREATE COLUMN ENCRYPTION KEY ImgCEK1 WITH VALUES (CLIENT_MASTER_KEY = ImgCMK1, ALGORITHM = AEAD_AES_256_CBC_HMAC_SHA256);");

创建加密表

在创建了客户端主密钥CMK和数据加密密钥CEK之后,就可以使用CEK创建加密表了。加密表的创建支持对加密列进行随机加密和确定性加密两种方式。

  • GSQL连接环境下创建加密表:

    【示例】

    1. openGauss=# CREATE TABLE creditcard_info (id_number int, name text encrypted with (column_encryption_key = ImgCEK, encryption_type = DETERMINISTIC),credit_card varchar(19) encrypted with (column_encryption_key = ImgCEK, encryption_type = DETERMINISTIC));

    参数说明

    ENCRYPTION_TYPE为ENCRYPTED WITH约束中的加密类型,encryption_type_value的值为[ DETERMINISTIC | RANDOMIZED ]。

  • JDBC环境下创建加密表:

    1. int rc3 = stmt.executeUpdate("CREATE TABLE creditcard_info (id_number int, name varchar(50) encrypted with (column_encryption_key = ImgCEK, encryption_type = DETERMINISTIC),credit_card varchar(19) encrypted with (column_encryption_key = ImgCEK1, encryption_type = DETERMINISTIC));");

向加密表插入数据并进行查询

创建了加密表以后,可以在密态数据库模式下(连接参数-C)向加密表中插入数据、查看数据。当使用普通环境(关掉连接参数-C)时,是无法对加密表进行操作的,查看加密表时也只能看到密文数据。

  • GSQL环境下向加密表插入数据并查看:

    1. openGauss=# INSERT INTO creditcard_info VALUES (1,'joe','6217986500001288393');
    2. INSERT 0 1
    3. openGauss=# INSERT INTO creditcard_info VALUES (2, 'joy','6219985678349800033');
    4. INSERT 0 1
    5. openGauss=# select * from creditcard_info where name = 'joe';
    6. id_number | name | credit_card
    7. -----------+------+---------------------
    8. 1 | joe | 6217986500001288393
    9. (1 row)

    全密态数据库 - 图3 说明: 使用非密态客户端查看该加密表数据时是密文。

    1. openGauss=# select id_number,name from creditcard_info;
    2. id_number | name
    3. -----------+-------------------------------------------
    4. 1 | \x011aefabd754ded0a536a96664790622487c4d36
    5. 2 | \x011aefabd76853108eb406c0f90e7c773b71648f
    6. (2 rows)
  • JDBC环境下向加密表插入数据并查看:

    1. // 插入数据
    2. int rc4 = stmt.executeUpdate("INSERT INTO creditcard_info VALUES (1,'joe','6217986500001288393');");
    3. // 查询加密表
    4. ResultSet rs = null;
    5. rs = stmt.executeQuery("select * from creditcard_info where name = 'joe';");
    6. // 关闭语句对象
    7. stmt.close();

上述我们列出的是全密态数据库特性的基本使用方法,更全面的使用介绍,可以参考官方文档中的对应章节。