背景 #
当前用户使用加解密配置时,只能配置明文列、密文列和辅助查询列的名称,但是无法配置这些列的字段定义,因此当用户执行相关 DDL 语句时,只能根据逻辑列的定义去创建加密列。改写后的明文列和密文列的类型和长度,都是按照逻辑列进行复制。这种改写方式,存在两个问题:
- 无法支持加密前后字段类型不同的加密算法(例如,数值类型加密之后变为字符串类型);
- 对于字段长度,用户也无法进行自定义,密文长度通常都大于明文长度;
如下所示,展示了创建表时,对于加密列的改写,我们看到 user_id 的定义 varchar(100) DEFAULT NULL 和 user_cipher 的定义 varchar(100) DEFAULT NULL 完全相同。
mysql> PREVIEW CREATE TABLE `t_encrypt` (`id` int(11) DEFAULT NULL, `user_id` varchar(100) DEFAULT NULL, `order_id` varchar(100) DEFAULT NULL) ENGINE=InnoDB;
+------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| data_source_name | sql |
+------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ds_0 | CREATE TABLE `t_encrypt` (`id` int(11) DEFAULT NULL, user_cipher varchar(100) DEFAULT NULL, user_plain varchar(100) DEFAULT NULL, order_cipher varchar(100) DEFAULT NULL) ENGINE=InnoDB |
+------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
为了提升功能的易用性,需要为加密列增加字段类型配置,允许用户灵活地进行配置。
数据加密提供了云端密钥管理功能和洗数功能,具体如下:
- 云端密钥管理
encrypt 采用的加密 key 明文配置在 props 文件中存在安全隐患,可以增加云端密钥管理功能通过 AWS 来管理加密的 key。
- 加密洗数
目前 DBPlusEngine 已经提供了加密的解决方案,对于新表新业务而言,直接使用加密规则配置即可,但是对于已有数据表,就需要将这些表中的明文字段进行洗数,转化为加密内容,同时如果用户需要更换密钥的话,我们也提供有对应的解密洗数功能,两者配合完成密钥的更换。
挑战 #
在真实业务场景中,相关业务开发团队则往往需要针对公司安全部门需求,自行实行并维护一套加解密系统。 而当加密场景发生改变时,自行维护的加密系统往往又面临着重构或修改风险。 此外,对于已经上线的业务,在不修改业务逻辑和 SQL 的情况下,透明化、安全低风险地实现无缝进行加密改造也相对复杂。
目标 #
通过增加加密列字段类型定义的配置,让用户执行 DDL 语句时,能够根据配置的明文列和密文列进行改写,让加解密功能更加易用。
核心概念 #
逻辑列 #
用于计算加解密列的逻辑名称,是 SQL 中列的逻辑标识。
逻辑列包含密文列(必须)、查询辅助列(可选)和明文列(可选)。
逻辑列类型(dataType) #
用于定义逻辑列的类型,例如 INT NOT NULL,VARCHAR(200) DEFAULT NULL 等,具体可以参见官方文档中各种方言字段的定义。例如 MySQL create statement 中 column_definition 的定义(https://dev.mysql.com/doc/refman/8.0/en/create-table.html)。
密文列(cipherColumn) #
加密后的数据列。
密文列类型(cipherDataType) #
用于定义密文列的类型,同逻辑列类型。
查询辅助列(assistedQueryColumn) #
用于查询的辅助列。 对于一些安全级别更高的非幂等加密算法,提供不可逆的幂等列用于查询。
查询辅助列类型(assistedQueryDataType) #
用于定义查询辅助列类型,同逻辑列类型。
明文列(plainColumn) #
存储明文的列,用于在加密数据迁移过程中仍旧提供服务。
在洗数结束后可以删除。
明文列类型(plainDataType) #
用于定义明文列类型,同逻辑列类型。
加密洗数(encrypting) #
批量对数据库中未加密数据进行加密。
解密洗数(decrypting) #
批量对数据库中加密数据进行解密。
实现原理 #
云端密钥管理 #
将密钥管理在云端,例如利用 AWS 的 secretKey 功能保存密钥,从而提升整个加密的安全性和便捷性。
程序在初始化加密算法时,会同 AWS 建立连接,从而获取存储在 AWS 中的相关密钥,然后将密钥存储在算法中。在整个数据加密的过程中不涉及与云端的网络交互。
加密洗数 #
加密洗数通过 DistSQL 来触发洗数任务,程序收到洗数任务的请求之后,会根据当前的洗数规则以及加密规则创建洗数任务。洗数任务主要由两部分构成,一部分是查询任务,一部分是更新任务,查询任务负责查询用户的表数据并获取需要加密的明文字段,然后推送到通道中;更新任务则从通道中获取数据,并加密更新。整个任务的创建以及执行过程都会与治理中心进行交互,因此用户可以通过相关 DistSQL 来查询任务进度以及清理任务。
使用规范 #
支持项 #
- 对数据库表中某个或多个列进行加解密;
- 兼容所有常用 SQL。
使用限制 #
- 需自行处理数据库中原始的存量数据;
- 模糊查询支持 %、_,暂不支持 escape;
- 加密字段无法支持查询不区分大小写功能;
- 加密字段无法支持比较操作,如:大于、小于、ORDER BY、BETWEEN 等;
- 加密字段无法支持计算操作,如:AVG、SUM 以及计算表达式。