GBase 8a透明存储加密encrypt功能使用

GBase 8a MPP Cluster 数据加密encrypt,提供对数据库落地数据的软加密功能,用来满足用户的安全需求,提高系统的安全性。数据加密按照数据文件中的 DC 为最小单位进行,可以实现表级或者列级不同粒度的加密要求。数据库中所有加密数据都使用同一个密钥,系统启动时会自动读取已创建的密钥文件内容。数据使用密钥文件内容加解密后,密钥文件内容就不能再改变。

密钥证书通过密码二次加密,在整个集群全部停止,再启动时,需要通过SQL提供密码进行激活。部分节点重启,不需要激活。

概述

数据加密支持的操作

  • 支持加密关键字 encrypt 建表;
  • 支持表级或者列级不同粒度的加密要求;
  • 支持表加密属性的查询;
  • 支持密钥证书管理包括密钥证书的创建、打开、关闭、口令修改、密钥转换操作
  • 支持密钥类型转换,即从明文密钥转换到密文密钥,或从密文密钥转换到明文密钥:
  • 明文密钥:无须用户口令,可随机生成也可手动输入;
  • 密文密钥:须用户输入口令,根据口令对随机生成的密钥加密存储;
  • 支持查询当前密钥证书状态;
  • 支持行存列加密。

证书管理

证书由用户创建,并设置启用密码。强烈建议用户备份生成的证书文件,并牢记密码,否则加密的数据将无法使用。

创建证书

创建明文、密文密钥证书,如果 password 为空,则创建明文密钥证书,不需要口令;如果 password 非空,则创建密文密钥证书,需要口令;密钥证书只有一份不能重复创建。

语法

CREATE ENCRYPTION CERTIFICATE IDENTIFIED BY ‘password’
[CONTENT ‘content_value’]

password 密钥证书口令
content_value:密钥内容关键字,可选项,如果不指定该关键字,则创建时由系统自动生成密钥;如果指定,则需要用户手动输入密钥,内容不做限制,最大支持 128 字节。

警告:
1、数据库并不记录密码,如果你忘记了密码,则证书无法打开,所有加密的数据也将不再能够读取。
2、密码保存在管理节点运行环境内(内存里),如有部分节点重启,无论是管理还是数据,只要尚有任意一个管理节点存活,密码就会自动同步给【新启动】的节点。但是当所有管理节点都停掉,比如断电,再次重启时,必须【人工】打开证书,因为数据库并不记录密码。

  • 建议对密钥证书进行备份,如果证书丢失会影响已有数据的解密操作;
  • 打开密文密钥证书后,方可对加密列做 dml 操作;
  • 关闭密文密钥证书后,所有对加密列的 dml 操作将会失效;
  • 密钥证书只有一份,即只能创建一次,不能重复创建;

证书位置

证书存放在 config 目录,集群环境下,gnode 与 gcluster 都会生成相同的密钥证书文件:
gnode:$GBASE_BASE/config/encryption.crt
gcluster:$GCLUSTER_BASE/config/encryption.crt

创建样例

如下创建了一个指定内容的证书,密码为12345678。只能建一个证书。

gbase> create encryption certificate identified by '12345678' content '12345678ABCDEFG';
Query OK, 0 rows affected (Elapsed: 00:00:00.02)

gbase> create encryption certificate identified by '12345678' content '12345678ABCDEFG';
ERROR 1850 (HY000): encryption certificate already exists.
gbase>


gbase> ^CAborted
[gbase@rh6-1 ~]$ ll /opt/gcluster/config/
total 28
-rw-r----- 1 gbase gbase   93 Dec  4 15:12 encryption.crt
-rw-r----- 1 gbase gbase 3120 Nov 30 14:44 gbase_8a_gcluster.cnf
-rw-r----- 1 gbase gbase   49 Oct 27 08:51 gcluster_uuid.cnf
-rw-r----- 1 gbase gbase  239 Oct 27 08:51 gcmmonit.conf
-rw-r----- 1 gbase gbase  851 Oct 27 08:51 gcmonit.conf
-rw-r----- 1 gbase gbase 4129 Oct 27 08:51 gc_recover.cnf
[gbase@rh6-1 ~]$ ll /opt/gnode/config/
total 16
-rw-r----- 1 gbase gbase   93 Dec  4 15:12 encryption.crt
-rw-r----- 1 gbase gbase 2025 Nov  5 12:16 gbase_8a_gbase.cnf
-rw-r----- 1 gbase gbase   49 Oct 27 08:51 gcluster_uuid.cnf
-rw-r----- 1 gbase gbase   91 Oct 27 08:51 synctool.conf
[gbase@rh6-1 ~]$

查看证书状态

通过如下元数据表查看证书当前状态

SELECT * FROM INFORMATION_SCHEMA.ENCRYPTION_CERTIFICATE_STATUS;
gbase> SELECT * FROM
    -> INFORMATION_SCHEMA.ENCRYPTION_CERTIFICATE_STATUS;
+------+-----------+----------+-------------+
| HOST | IS_CREATE | KEY_TYPE | OPEN_STATUS |
+------+-----------+----------+-------------+
| ::   | YES       |        1 | OFF         |
+------+-----------+----------+-------------+
1 row in set (Elapsed: 00:00:00.00)

KEY_TYPE :0是明文,1是密文。
OPEN_STATUS:OFF 代表证书没有打开,尚未生效, ON是生效中。

修改证书密码

通过如下的语法修改证书的打开密码。其中前面是老密码,后面是新密码。

gbase> alter encryption certificate identified by '12345678' to '123456789';
Query OK, 0 rows affected (Elapsed: 00:00:00.02)

gbase>

打开证书

如果密码不对,是无法打开证书的。

gbase> alter encryption certificate open identified by '12345678';
ERROR 1850 (HY000): decrypt failed, please check password.
gbase>
gbase> alter encryption certificate open identified by '123456789';
Query OK, 0 rows affected (Elapsed: 00:00:00.01)

gbase> SELECT * FROM INFORMATION_SCHEMA.ENCRYPTION_CERTIFICATE_STATUS;
+------+-----------+----------+-------------+
| HOST | IS_CREATE | KEY_TYPE | OPEN_STATUS |
+------+-----------+----------+-------------+
| ::   | YES       |        1 | ON          |
+------+-----------+----------+-------------+
1 row in set (Elapsed: 00:00:00.00)

gbase>

关闭证书

通过如下方式关闭证书。

gbase> alter encryption certificate close;
Query OK, 0 rows affected (Elapsed: 00:00:00.01)

gbase> SELECT * FROM INFORMATION_SCHEMA.ENCRYPTION_CERTIFICATE_STATUS;
+------+-----------+----------+-------------+
| HOST | IS_CREATE | KEY_TYPE | OPEN_STATUS |
+------+-----------+----------+-------------+
| ::   | YES       |        1 | OFF         |
+------+-----------+----------+-------------+
1 row in set (Elapsed: 00:00:00.00)

存储加密

通过encypt关键字,在建表时,给指定的表或列设置加密属性。不支持修改加密属性。你可以通过重建一个新表或新列,实现修改加密属性。

证书必须处于打开状态,否则无法向加密表插入数据。

整表加密

gbase> SELECT * FROM INFORMATION_SCHEMA.ENCRYPTION_CERTIFICATE_STATUS;
+------+-----------+----------+-------------+
| HOST | IS_CREATE | KEY_TYPE | OPEN_STATUS |
+------+-----------+----------+-------------+
| ::   | YES       |        1 | OFF         |
+------+-----------+----------+-------------+
1 row in set (Elapsed: 00:00:00.00)

gbase> create table t_encrypt(id int)encrypt;
Query OK, 0 rows affected (Elapsed: 00:00:00.97)

gbase> insert into t_encrypt values(1),(2);
ERROR 1705 (HY000): gcluster DML error: Commit failed, no successful node of some suffix
cause: (GBA-01EX-700) Gbase general error: Encrypt key invalid.
(GBA-01EX-700) Gbase general error: Encrypt key invalid.
gbase>

打开证书,然后可以正常的处理数据了。

gbase> alter encryption certificate open identified by '123456789';
Query OK, 0 rows affected (Elapsed: 00:00:00.00)

gbase> insert into t_encrypt values(1),(2);
Query OK, 2 rows affected (Elapsed: 00:00:00.21)
Records: 2  Duplicates: 0  Warnings: 0

gbase> select * from t_encrypt;
+------+
| id   |
+------+
|    1 |
|    2 |
+------+
2 rows in set (Elapsed: 00:00:00.01)

gbase>

加密列

gbase> create table t_encrypt_2(id int,name varchar(100) encrypt);
Query OK, 0 rows affected (Elapsed: 00:00:00.79)
gbase> insert into t_encrypt_2 values(1,'first'),(2,'second');

Query OK, 2 rows affected (Elapsed: 00:00:00.74)
Records: 2  Duplicates: 0  Warnings: 0

gbase> select *from t_encrypt_2;
+------+--------+
| id   | name   |
+------+--------+
|    1 | first  |
|    2 | second |
+------+--------+
2 rows in set (Elapsed: 00:00:00.01)

对于非加密的列,即使证书关闭,也可以查询。加密列则报错。

gbase> alter encryption certificate close;
Query OK, 0 rows affected (Elapsed: 00:00:00.00)

gbase> select *from t_encrypt_2;
ERROR 1708 (HY000): [10.0.2.202:5050](GBA-02AD-0005)Failed to query in gnode:
DETAIL: (GBA-01EX-700) Gbase general error: Decrypt key invalid.
SQL: SELECT /*::ffff:10.0.2.201_8_24_2020-12-04_15:52:38*/ /*+ TID('3538981') */ `testdb.t_encrypt_2`.`id` AS `id`, `testdb.t_encrypt_2`.`name` AS `name` FROM `testdb`.`t_encrypt_2_n1` `testdb.t_encrypt_2`
gbase> select id from t_encrypt_2;
+------+
| id   |
+------+
|    1 |
|    2 |
+------+
2 rows in set (Elapsed: 00:00:00.03)

gbase> select name from t_encrypt_2;
ERROR 1708 (HY000): [10.0.2.202:5050](GBA-02AD-0005)Failed to query in gnode:
DETAIL: (GBA-01EX-700) Gbase general error: Decrypt key invalid.
SQL: SELECT /*::ffff:10.0.2.201_8_26_2020-12-04_15:52:48*/ /*+ TID('3538983') */ `testdb.t_encrypt_2`.`name` AS `name` FROM `testdb`.`t_encrypt_2_n1` `testdb.t_encrypt_2`
gbase>

注意

整表加密,也就是在表属性上使用encrypt,只是在创建时的列全部加密。如果后续有增加列,如果不写加密属性,默认还是不加密的。否则就没有办法在一个加密表上,增加非加密列了。

gbase> create table t_encrypt2(id int,name varchar(100))encrypt;
Query OK, 0 rows affected (Elapsed: 00:00:00.09)

gbase> show create table t_encrypt2;
+------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table      | Create Table                                                                                                                                                                             |
+------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t_encrypt2 | CREATE TABLE "t_encrypt2" (
  "id" int(11) DEFAULT NULL ENCRYPT ,
  "name" varchar(100) DEFAULT NULL ENCRYPT
) ENCRYPT  ENGINE=EXPRESS DEFAULT CHARSET=utf8 TABLESPACE='sys_tablespace' |
+------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (Elapsed: 00:00:00.00)

gbase> alter table t_encrypt2 add birth date;
Query OK, 0 rows affected (Elapsed: 00:00:00.12)
Records: 0  Duplicates: 0  Warnings: 0

gbase> show create table t_encrypt2;
+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table      | Create Table                                                                                                                                                                                                          |
+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t_encrypt2 | CREATE TABLE "t_encrypt2" (
  "id" int(11) DEFAULT NULL ENCRYPT ,
  "name" varchar(100) DEFAULT NULL ENCRYPT ,
  "birth" date DEFAULT NULL
) ENCRYPT  ENGINE=EXPRESS DEFAULT CHARSET=utf8 TABLESPACE='sys_tablespace' |
+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (Elapsed: 00:00:00.00)

gbase> insert into "t_encrypt2" values (1,'first','2020-01-01');
ERROR 1705 (HY000): gcluster DML error: No successful nodes, (GBA-01EX-700) Gbase general error: Encrypt key invalid.

gbase> insert into "t_encrypt2" (birth) values ('2020-01-01');
Query OK, 1 row affected (Elapsed: 00:00:00.05)

gbase> select * from t_encrypt2;
+------+------+------------+
| id   | name | birth      |
+------+------+------------+
| NULL | NULL | 2020-01-01 |
+------+------+------------+
1 row in set (Elapsed: 00:00:00.01)

需要加密列时,指定列的encrypt属性。

gbase> alter table t_encrypt2 add birth2 date encrypt;
Query OK, 1 row affected (Elapsed: 00:00:00.14)
Records: 1  Duplicates: 1  Warnings: 0

gbase> show create table t_encrypt2;
+------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table      | Create Table                                                                                                                                                                                                                                                 |
+------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t_encrypt2 | CREATE TABLE "t_encrypt2" (
  "id" int(11) DEFAULT NULL ENCRYPT ,
  "name" varchar(100) DEFAULT NULL ENCRYPT ,
  "birth" date DEFAULT NULL,
  "birth2" date DEFAULT NULL ENCRYPT
) ENCRYPT  ENGINE=EXPRESS DEFAULT CHARSET=utf8 TABLESPACE='sys_tablespace' |
+------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (Elapsed: 00:00:00.01)

gbase> insert into "t_encrypt2" (birth2) values ('2020-01-01');
ERROR 1705 (HY000): gcluster DML error: No successful nodes, (GBA-01EX-700) Gbase general error: Encrypt key invalid.
gbase>

性能损失

根据公司测试,加密算法本身性能下降接近300%,也就是单纯从磁盘读取数据,对比读取数据后解密。

在实际业务中,需要考虑磁盘读取部分,在整个业务中占用的比例,还要考虑冷热数据和缓冲等影响。同时,在有非加密列参与的业务,需要考虑到加密列所占比例,比例越小影响越小。

性能影响 = 磁盘部分所占比例 * 加密列在所有参与计算列的比例。

如果数据少而计算量大,比如大量的group,OLAP计算,JOIN等,则整体性能下降就较少,一般在5-10%。最差的情况,比如【冷数据】,无缓存,简单的select *,将下降300%。

普通估算,可以考虑在10-30%之间,包括加载。

数据膨胀

无膨胀。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注