从MySQL 5.7开始,InnoDB支持对独立表空间静态数据加密,是引擎内部数据页级别的加密手段。静态加密功能依赖于keyring组件或插件,插件会将keyring数据存储在服务器主机的本地文件系统中。当数据页写入文件系统时加进行加密,从数据文件读到内存中时解密,对客户端而言是无感知的。
如上图所示,InnoDB使用两层加密密钥架构,包括一个主加密密钥(master encryption key,master key )和表空间密钥( tablespace key ) 。
主加密密钥用于加密、解密表空间密钥,其存储在磁盘上。
表空间密钥用于加密表空间中的数据。表空间密钥密文由主密钥加密并存储在表空间文件的头部,其存储在表空间文件的头部中。
当一个应用程序或认证用户想要访问加密的表空间数据时,InnoDB使用主加密密钥来解密表空间密钥(存储在表空间中的表空间密钥的密文)。从而得到表空间密钥的明文 ,再用 表空间密钥明文解密数据。
其中 表空间密钥的明文永远不会改变,但是主加密密钥可以根据需要改变。主加密密钥可以随时改变(比如使用 ALTER INSTANCE ROTATE INNODB MASTER KEY),这个称为 master key rotation。因为 表空间密钥的明文不会变,所以更新主加密密钥之后只需要把表空间密钥的明文重新加密(用新的主加密密钥加密)得到表空间密钥的密文并写入文件头部即可。
从8.0.16,对InnoDB单表空间、通用表空间、系统表空间和Redo、Undo文件都能静态加密。表空间加密不能混合使用加密和未加密的块,故表空间是未加密的或已加密的。
InnoDB存储引擎中数据是按照表空间来组织存储的,对用户表支持两种类型的表空间。第一种为file-per-table,每个表存储在单独的表空间中。第二种类型是通用表空间,可以在一个表空间中存储多个表,因此,通用表空间不能同时包含未加密表和已加密表。
下面,介绍如何在不同级别上实现加密。
1:系统级别进行加密
通过系统范围的配置设置default_table_encryption='y',所有新表都将被加密。
show variables like 'default_table_encryption'; 来确认当前配置。
2:库级进行加密
创建库时,可以设置默认的加密属性。之后在模式中创建的所有表都将继承该模式的默认加密设置。
create database db1 default encryption ='Y';
use db1;
(1)file-per-table表空间
create table t1(c1 int);
show create table t1;
+-------+-------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+-------------------------------------------------------------------------------------------------------------------------------+
| t1 | CREATE TABLE `t1` (
`c1` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ENCRYPTION='Y' |
为“ db1”配置了加密,则所有单表(默认file-per-table表空间,例如“ ts1”)都会加密。
(2)通用表空间
CREATE TABLESPACE `ts2` ADD DATAFILE 'ts2.ibd' ENCRYPTION='Y' ;
通用表空间(例如“ ts2”)加密。
create table t2(c1 int) tablespace=ts2;
show create table t2;
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t2 | CREATE TABLE `t2` (
`c1` int DEFAULT NULL
) /*!50100 TABLESPACE `ts2` */ ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci /*!80016 ENCRYPTION='Y' */ |
3 通用表空间级别进行加密
通用表空间只能保存已加密或未加密的表。若已指定通用表空间加密。
(1)在加密库中创建表。例如,创建通用表空间 ts2 并将其配置为加密;创建“ db1”(加密库)中的表“ t2”指定其存储在“ ts2”中。
(2)在不加密的库中
create database db2;
create table db2.t2(c1 int) ENCRYPTION='y' tablespace=ts2;
在'db2'中创建表并要将其存储在加密的通用表空间 ts2 中,必须使用加密语句 ENCRYPTION='y'显示指定才能成功。
综上,此文简单介绍了keyring二级加密机制以及如何实现在不同级别(系统级别、库级、表空间级别)的静态加密。