全密态数据库
全密态数据库是指能够解决数据全生命周期的隐私保护问题,使得系统无论在何种业务场景和环境下,数据在传输、运算以及存储的各个环节始终都处于密文状态,同时密钥掌握在授权用户手中的数据库管理系统。
加密模型
全密态数据库使用多级加密模型,加密模型中涉及3个对象:数据、列密钥和主密钥,其关系如图1所示:
以下是对3个对象的介绍:
- 数据:
- SQL语法中包含的数据,比如INSERT... VALUES ('data')语法中包含'data'。
- 从数据库服务端返回的查询结果,如执行SELECT语法返回的查询结果。
密态数据库会在驱动中,对SQL语法中属于加密列的数据进行加密,对数据库服务端返回的属于加密列的查询结果进行解密。
- 列密钥:数据由列密钥进行加密,列密钥由数据库驱动生成或由用户手动导入,列密钥密文存储在数据库服务端。
- 主密钥:列密钥由主密钥加密,主密钥由外部密钥管理者生成并存储。数据库驱动会自动访问外部密钥管理者,以实现对列密钥进行加解密。
密钥管理
全密态数据库目前支持以下密钥管理工具进行独立管理:
- Huawei KMS:由华为云提供的在线密钥管理服务,提供创建、删除、查询和备份密钥等功能,并支持在线使用密钥对数据进行加解密。
- user_token:由用户提供的密码在客户端派生密钥,或者直接对接密钥。
- sdf_kms:支持基于鲲鹏TEE的内生密钥管理、支持三未信安SJJ1994加密机。
数据库驱动
全密态数据库目前支持的数据库驱动有gsql、JDBC和GO驱动。
使用gsql执行SQL语句
执行本节的SQL语句前,请确保已提前生成主密钥,并确认访问主密钥的参数。
本节以完整的执行流程为例,介绍如何使用密态数据库语法,包括三个阶段:使用DDL阶段、使用DML阶段、清理阶段。
- 连接数据库,并通过-C参数开启全密态开关
gsql -p PORT -d DATABASE -h HOST -U USER -W PASSWORD -r -C
- 通过元命令设置访问主密钥的参数
注意:从keyType字符串开始,不要添加换行,不要添加空格,否则gsql工具无法识别完整参数。
基于三未信安SJJ1994加密机密钥管理:
gaussdb=# \key_info keyType=sdf_kms,library_path={动态库的路径},library_version=SJJ1994,kek_algo=SGD_SM4_CBC,mac_algo=SGD_SM4_MAC,dkey_algo=SGD_SM4_CBC
- 使用三未信安SJJ1994加密机前,需要正确配置ini文件,并且保证加密机能正常连接使用。
- library_path可以使用绝对路径或相对路径(相对于$GAUSSHOME/lib)。
- kek_algo是密钥加密密钥(KEK)用于加密会话密钥的算法,允许配置算法:SGD_SM4_ECB(默认算法)、SGD_SM4_CBC、SGD_SM4_CTR、SGD_AES_ECB、SGD_AES_CBC、SGD_AES_CTR。
- dkey_algo是会话密钥用于加密数据密钥的算法,允许配置算法:SGD_SM4_CBC、SGD_SM4_CTR、SGD_AES_CBC、SGD_AES_CTR。
- mac_algo是会话密钥用于对数据密钥进行完整性校验的算法,允许配置算法:SGD_SM4_MAC、SGD_AES_MAC。
- library_version为可选配置,主要用于定制化对接,当前仅支持配置为SJJ1994。
- kek_algo要与创建CMK密钥时指定的KEY_PATH匹配,即均为AES系列算法或SM4系列算法。
- 目前支持gsql和JDBC驱动。
基于鲲鹏TEE内生密钥管理:
gaussdb=# \key_info keyType=sdf_kms,library_path={动态库的路径},mac_algo=SGD_SM4_MAC,dkey_algo=SGD_SM4_CBC示例:\key_info KeyType=sdf_kms,library_path=./libsdf.so,mac_algo=SGD_SM4_MAC,dkey_algo=SGD_SM4_CBC
华为云支持两种认证方式,两种认证方式的参数个数与参数类型不同,选择其中一种方式即可。
- 认证方式一 aksk认证
gaussdb=# \key_info keyType=huawei_kms,kmsProjectId={项目ID},ak={AK},sk={SK}参数获取:生成主密钥阶段介绍了如何获取相关参数:项目ID、AK、SK。
示例:\key_info keyType=huawei_kms,kmsProjectId=0b59929e8100268a2f22c01429802728,ak=XMAUMJY******DFWLQW,sk=ga6rO8lx1Q4uB*********2gf80muIzUX
- 认证方式二 账号密码认证
gaussdb=# \key_info keyType=huawei_kms,iamUrl={IAM服务器地址},iamUser={IAM用户名},iamPassword={IAM用户密码},iamDomain={账号名},kmsProject={项目}参数获取:生成主密钥阶段介绍了如何获取相关参数:IAM服务器地址、IAM用户名、IAM用户密码、账号名、项目。
示例:\key_info keyType=huawei_kms,iamUrl=https://iam.example.com/v3/auth/tokens,iamUser=test,iamPassword=*********,iamDomain=test_account,kmsProject=xxx
- 定义主密钥 在生成主密钥阶段,密钥服务已生成并存储主密钥,执行本语法只是将主密钥的相关信息存储在数据库中,方便以后访问。该语法详细格式参考:《参考》中“SQL参考 > SQL语法 > C > CREATE CLIENT MASTER KEY”章节。
gaussdb=# CREATE CLIENT MASTER KEY cmk2 WITH ( KEY_STORE = sdf_kms, KEY_PATH = '{密钥加密密钥ID}'); gaussdb=# CREATE CLIENT MASTER KEY cmk1 WITH ( KEY_STORE = huawei_kms , KEY_PATH = '{KMS服务器地址}/{密钥ID}', ALGORITHM = AES_256); CREATE CLIENT MASTER KEY
- 定义列密钥 列密钥由上一步定义的主密钥加密。详细语法参考:《参考》中“SQL参考 > SQL语法 > C > CREATE COLUMN ENCRYPTION KEY”章节。
gaussdb=# CREATE COLUMN ENCRYPTION KEY cek1 WITH VALUES (CLIENT_MASTER_KEY = cmk1, ALGORITHM = AES_256_GCM); gaussdb=# CREATE COLUMN ENCRYPTION KEY cek2 WITH VALUES (CLIENT_MASTER_KEY = cmk2, ALGORITHM = SM4_HMAC_SM3);
- 定义加密表 本示例中,通过语法指定表中name和credit_card为加密列。
gaussdb=# CREATE TABLE creditcard_info ( id_number int, name text encrypted with (column_encryption_key = cek1, encryption_type = DETERMINISTIC), credit_card varchar(19) encrypted with (column_encryption_key = cek1, encryption_type = DETERMINISTIC)); NOTICE: The 'DISTRIBUTE BY' clause is not specified. Using 'id_number' as the distribution column by default. HINT: Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column. CREATE TABLE - 对加密表进行其他操作
-- 向加密表写入数据 gaussdb=# INSERT INTO creditcard_info VALUES (1,'joe','6217986500001288393'); INSERT 0 1 gaussdb=# INSERT INTO creditcard_info VALUES (2, 'joy','6219985678349800033'); INSERT 0 1 -- 从加密表中查询数据 gaussdb=# select * from creditcard_info where name = 'joe'; id_number | name | credit_card -----------+------+--------------------- 1 | joe | 6217986500001288393 -- 更新加密表中数据 gaussdb=# update creditcard_info set credit_card = '80000000011111111' where name = 'joy'; UPDATE 1 -- 向表中新增一列加密列 gaussdb=# ALTER TABLE creditcard_info ADD COLUMN age int ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = cek1, ENCRYPTION_TYPE = DETERMINISTIC); ALTER TABLE -- 从表中删除一列加密列 gaussdb=# ALTER TABLE creditcard_info DROP COLUMN age; ALTER TABLE -- 从系统表中查询主密钥信息 gaussdb=# SELECT * FROM gs_client_global_keys; global_key_name | key_namespace | key_owner | key_acl | create_date -----------------+---------------+-----------+---------+---------------------------- cmk1 | 2200 | 10 | | 2021-04-21 11:04:00.656617 (1 rows) -- 从系统表中查询列密钥信息 gaussdb=# SELECT column_key_name,column_key_distributed_id ,global_key_id,key_owner FROM gs_column_keys; column_key_name | column_key_distributed_id | global_key_id | key_owner -----------------+---------------------------+---------------+----------- cek1 | 760411027 | 16392 | 10 (1 rows) -- 查看表中列的元信息 gaussdb=# \d creditcard_info Table "public.creditcard_info" Column | Type | Modifiers -------------+-------------------+------------ id_number | integer | name | text | encrypted credit_card | character varying | encrypted
- 清理阶段
-- 删除加密表 gaussdb=# DROP TABLE creditcard_info; DROP TABLE -- 删除列密钥 gaussdb=# DROP COLUMN ENCRYPTION KEY cek1; DROP COLUMN ENCRYPTION KEY gaussdb=# DROP COLUMN ENCRYPTION KEY cek2; DROP COLUMN ENCRYPTION KEY -- 删除主密钥 gaussdb=# DROP CLIENT MASTER KEY cmk1; DROP CLIENT MASTER KEY gaussdb=# DROP CLIENT MASTER KEY cmk2; DROP CLIENT MASTER KEY
