Logo
数据加密

背景 #

当前用户使用加解密配置时,只能配置明文列、密文列和辅助查询列的名称,但是无法配置这些列的字段定义,因此当用户执行相关 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 以及计算表达式。