InnoDB支持独立表空间、通用表空间、mysql系统表空间、重做日志和撤消日志的静态数据加密。
从 MySQL 8.0.16 开始,还支持为模式和通用表空间设置加密默认值,这允许 DBA 控制在这些模式和表空间中创建的表是否被加密。
关于静态数据加密
InnoDB使用两层加密密钥架构,由主加密密钥和表空间密钥组成。当表空间被加密时,表空间密钥被加密并存储在表空间头中。当应用程序或经过身份验证的用户想要访问加密的表空间数据时, InnoDB使用主加密密钥来解密表空间密钥。表空间密钥的解密版本永远不会更改,但可以根据需要更改主加密密钥。此操作称为主密钥轮换。
静态数据加密功能依赖于密钥环组件或插件进行主加密密钥管理。
所有 MySQL 版本都提供了一个 component_keyring_file组件和 keyring_file插件,每个都将密钥环数据存储在服务器主机本地的文件中。
MySQL 企业版提供额外的密钥环组件和插件:
·
component_keyring_encrypted_file:将密钥环数据存储在服务器主机本地的加密的、受密码保护的文件中。
· keyring_encrypted_file:将密钥环数据存储在服务器主机本地的加密的、受密码保护的文件中。
· keyring_okv:一个 KMIP 1.1 插件,用于与 KMIP 兼容的后端密钥环存储产品。支持的 KMIP 兼容产品包括集中式密钥管理解决方案,例如 Oracle Key Vault、Gemalto KeySecure、Thales Vormetric 密钥管理服务器和 Fornetix Key Orchestration。
· keyring_aws:与 Amazon Web Services Key Management Service (AWS KMS) 进行通信,作为密钥生成的后端,并使用本地文件进行密钥存储。
· keyring_hashicorp:与 HashiCorp Vault 通信以进行后端存储。
安全可靠的加密密钥管理解决方案对于安全性和符合各种安全标准至关重要。当静态数据加密功能使用集中式密钥管理解决方案时,该功能称为“ MySQL 企业透明数据加密 (TDE) ”。
静态数据加密功能支持基于高级加密标准 (AES) 块的加密算法。它使用电子密码本 (ECB) 块加密模式进行表空间密钥加密,使用密码块链接 (CBC) 块加密模式进行数据加密。
加密先决条件
1、必须在启动时安装和配置密钥环组件或插件。提前加载确保组件或插件在 InnoDB存储引擎初始化之前可用。
一次只能启用一个密钥环组件或插件。不支持启用多个密钥环组件或插件,结果可能与预期不同。
2、加密生产数据时,请确保采取措施防止主加密密钥丢失。如果主加密密钥丢失,则存储在加密表空间文件中的数据将无法恢复。如果您使用 component_keyring_file、
component_keyring_encrypted_file组件或keyring_file、keyring_encrypted_file插件,请在创建第一个加密表空间之后、主密钥轮换之前和主密钥轮换之后立即创建密钥环数据文件的备份。对于每个组件,其配置文件指示数据文件位置。keyring_file_data 配置选项定义keyring_file插件的密钥环数据文件位置。这
keyring_encrypted_file_data 配置选项定义keyring_encrypted_file插件的密钥环数据文件位置。如果您使用keyring_okv或 keyring_aws插件,请确保您已执行必要的配置。
为模式和通用表空间定义加密默认值
从 MySQL 8.0.16 开始, default_table_encryption系统变量定义了模式和通用表空间的默认加密设置。CREATE TABLESPACE和 CREATE SCHEMA操作在未明确指定ENCRYPTION子句时应用 default_table_encryption设置。
ALTER SCHEMA和ALTER TABLESPACE操作不应用default_table_encryption设置。必须明确指定ENCRYPTION子句以更改现有模式或通用表空间的加密 。
default_table_encryption 变量可以为单个客户端连接设置,也可以使用 SET 语法全局设置。例如,以下语句全局启用默认模式和表空间加密:
mysql> SET GLOBAL default_table_encryption=ON;
架构的默认加密设置也可以在创建或更改架构时使用DEFAULT ENCRYPTION子句定义,如下例所示:
mysql> CREATE SCHEMA test DEFAULT ENCRYPTION = 'Y';
如果创建模式时未指定DEFAULT ENCRYPTION子句, 则应用default_table_encryption设置。必须指定DEFAULT ENCRYPTION子句以更改现有模式的默认加密。否则,架构将保留其当前加密设置。
默认情况下,表会继承创建它的模式或通用表空间的加密设置。例如,在启用加密的模式中创建的表默认是加密的。这种行为使 DBA 能够通过定义和强制执行模式和通用表空间加密默认值来控制表加密使用。
通过启用系统变量
table_encryption_privilege_check 来强制实施加密默认值。启用
table_encryption_privilege_check后,当使用不同于default_table_encryption设置的加密设置创建或更改模式或通用表空间时,或者在使用不同于默认模式加密的加密设置创建或更改表时,会发生权限检查。禁用
table_encryption_privilege_check时 ,不会进行权限检查,并且允许前面提到的操作继续进行并发出警告。
启用
table_encryption_privilege_check时需要TABLE_ENCRYPTION_ADMIN 权限才能覆盖默认加密设置 。DBA 可以授予此权限,使用户能够 在创建或更改模式或通用表空间时偏离default_table_encryption设置,或者在创建或更改表时偏离默认模式加密。此特权不允许在创建或更改表时偏离通用表空间的加密。表必须具有与其所在的通用表空间相同的加密设置。
独立表空间加密
从 MySQL 8.0.16 开始,独立表空间继承了创建表的模式的默认加密,除非在CREATE TABLE语句中明确指定了ENCRYPTION子句 。在 MySQL 8.0.16 之前, 必须指定ENCRYPTION子句以启用加密。
mysql> CREATE TABLE t1 (c1 INT) ENCRYPTION = 'Y';
要更改现有独立表空间的加密,必须指定一个ENCRYPTION子句。
mysql> ALTER TABLE t1 ENCRYPTION = 'Y';
从 MySQL 8.0.16 开始,如果 启用了
table_encryption_privilege_check变量,则指定具有与默认模式加密不同的设置的ENCRYPTION 子句需要 TABLE_ENCRYPTION_ADMIN特权。
通用表空间加密
从 MySQL 8.0.16 开始,default_table_encryption变量确定新创建的通用表空间的加密,除非在CREATE TABLESPACE语句中明确指定ENCRYPTION子句 。在 MySQL 8.0.16 之前,必须指定一个ENCRYPTION 子句来启用加密。
mysql> CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' ENCRYPTION = 'Y' Engine=InnoDB;
要更改现有通用表空间的加密, 必须指定一个ENCRYPTION子句。
mysql> ALTER TABLESPACE ts1 ENCRYPTION = 'Y';
从 MySQL 8.0.16 开始,如果 启用了
table_encryption_privilege_check变量,则指定具有default_table_encryption 与设置不同的设置的ENCRYPTION子句需要TABLE_ENCRYPTION_ADMIN 特权。
双写文件加密
从 MySQL 8.0.23 开始提供对双写文件的加密支持。InnoDB自动加密属于加密表空间的双写文件页面。无需任何操作。双写文件页面使用关联表空间的加密密钥进行加密。写入表空间数据文件的相同加密页面也写入双写文件。属于未加密表空间的双写文件页保持未加密状态。
在恢复期间,加密的双写文件页面未加密并检查是否损坏。
mysql系统表空间加密
mysql从 MySQL 8.0.16 开始提供对系统表空间的加密支持。
mysql系统表空间包含 mysql系统数据库和 MySQL 数据字典表。默认情况下它是未加密的。要为mysql系统表空间启用加密,请在ALTER TABLESPACE语句中指定表空间名称和ENCRYPTION选项 。
mysql> ALTER TABLESPACE mysql ENCRYPTION = 'Y';
要禁用mysql系统表空间的加密,请使用 ALTER TABLESPACE ENCRYPTION = 'N'语句进行设置。
mysql> ALTER TABLESPACE mysql ENCRYPTION = 'N';
mysql 为系统表空间 启用或禁用加密需要实例中所有表的CREATE TABLESPACE特权(CREATE TABLESPACE on *.*)。
重做日志加密
使用配置选项innodb_redo_log_encrypt 启用重做日志数据加密 。默认情况下禁用重做日志加密。
与表空间数据一样,重做日志数据加密发生在重做日志数据写入磁盘时,而解密发生在重做日志数据从磁盘读取时。一旦重做日志数据被读入内存,它就是未加密的形式。重做日志数据使用表空间加密密钥进行加密和解密。
启用innodb_redo_log_encrypt后,磁盘上存在的未加密重做日志页面保持未加密状态,并且新的重做日志页面以加密形式写入磁盘。同样, innodb_redo_log_encrypt禁用时,磁盘上存在的加密重做日志页面保持加密状态,新的重做日志页面以未加密的形式写入磁盘。
从 MySQL 8.0.30 开始,重做日志加密元数据(包括表空间加密密钥)存储在具有最新检查点 LSN 的重做日志文件的标头中。在 MySQL 8.0.30 之前,重做日志加密元数据,包括表空间加密密钥,存储在第一个重做日志文件的标头中。如果删除带有加密元数据的重做日志文件,则重做日志加密被禁用。
启用重做日志加密后,没有密钥环组件或插件或没有加密密钥的正常重启是不可能的,因为InnoDB必须能够在启动期间扫描重做页面,如果重做日志页面被加密,这是不可能的。如果没有密钥环组件或插件或加密密钥,则只能在没有重做日志 ( SRV_FORCE_NO_LOG_REDO) 的情况下强制启动。
撤消日志加密
使用配置选项innodb_undo_log_encrypt 启用撤消日志数据加密 。撤消日志加密适用于驻留在撤消表空间中的撤消日志。
与表空间数据一样,撤消日志数据加密发生在撤消日志数据写入磁盘时,而撤消日志数据从磁盘读取时发生解密。一旦撤消日志数据被读入内存,它就是未加密的形式。撤消日志数据使用表空间加密密钥进行加密和解密。
启用innodb_undo_log_encrypt时,磁盘上存在的未加密撤消日志页面保持未加密状态,新的撤消日志页面以加密形式写入磁盘。同样, innodb_undo_log_encrypt禁用时,磁盘上存在的加密撤消日志页面保持加密状态,并且新的撤消日志页面以未加密的形式写入磁盘。
撤消日志加密元数据(包括表空间加密密钥)存储在撤消日志文件的标头中。
万能钥匙轮换
应定期轮换主加密密钥,并在您怀疑密钥已被泄露时进行轮换。
主密钥轮换是一个原子的、实例级的操作。每次轮换主加密密钥时,MySQL 实例中的所有表空间密钥都会重新加密并保存回各自的表空间标头。作为原子操作,一旦启动轮换操作,所有表空间键的重新加密必须成功。如果主密钥轮换因服务器故障而中断,InnoDB则在服务器重新启动时前滚操作。
轮换主加密密钥只会更改主加密密钥并重新加密表空间密钥。它不会解密或重新加密关联的表空间数据。
轮换主加密密钥需要 ENCRYPTION_KEY_ADMIN特权(或已弃用的SUPER特权)。
要轮换主加密密钥,请运行:
mysql> ALTER INSTANCE ROTATE INNODB MASTER KEY;
ALTER INSTANCE ROTATE INNODB MASTER KEY支持并发 DML。但是,它不能与表空间加密操作同时运行,并且会使用锁来防止并发执行可能引起的冲突。如果一个ALTER INSTANCE ROTATE INNODB MASTER KEY操作正在运行,它必须在表空间加密操作可以继续之前完成,反之亦然。
加密和恢复
如果在加密操作期间发生服务器故障,则在重新启动服务器时前滚操作。对于一般表空间,加密操作从最后处理的页面在后台线程中恢复。
如果在主密钥轮换期间发生服务器故障, InnoDB则在服务器重新启动时继续操作。
密钥环组件或插件必须在存储引擎初始化之前加载,以便在InnoDB初始化和恢复活动访问表空间数据之前,可以从表空间头中检索解密表空间数据页所需的信息。
当InnoDB初始化和恢复开始时,主密钥轮换操作恢复。由于服务器故障,某些表空间密钥可能已经使用新的主加密密钥进行了加密。InnoDB从每个表空间头读取加密数据,如果数据表明表空间密钥是使用旧的主加密密钥加密的,InnoDB则从密钥环中检索旧密钥并使用它来解密表空间密钥。 InnoDB然后使用新的主加密密钥重新加密表空间密钥,并将重新加密的表空间密钥保存回表空间头。
导出加密表空间
表空间导出仅支持独立表空间。
导出加密表空间时, InnoDB生成用于加密表空间密钥的传输密钥。加密的表空间密钥和传输密钥存储在一个 tablespace_name.cfp 文件中。执行导入操作需要此文件和加密的表空间文件。导入时, InnoDB使用传输密钥解密 tablespace_name.cfp 文件中的表空间密钥。
加密和复制
1、ALTER INSTANCE ROTATE INNODB MASTER KEY语句仅在源和副本运行支持表空间加密的 MySQL 版本的复制环境中受支持。
2、成功的ALTER INSTANCE ROTATE INNODB MASTER KEY语句被写入二进制日志以在副本上进行复制。
3、如果一条ALTER INSTANCE ROTATE INNODB MASTER KEY语句失败,它不会记录到二进制日志中,也不会复制到副本上。
4、如果密钥环组件或插件安装在源上但未安装在副本上,则ALTER INSTANCE ROTATE INNODB MASTER KEY操作复制失败。
5、如果源和副本都安装了keyring_file或 keyring_encrypted_file插件,但副本没有密钥环数据文件,则复制的ALTER INSTANCE ROTATE INNODB MASTER KEY语句会在副本上创建密钥环数据文件(假设密钥环文件数据未缓存在内存中)。ALTER INSTANCE ROTATE INNODB MASTER KEY使用缓存在内存中的密钥环文件数据(如果可用)。
识别加密表空间和模式
INFORMATION_SCHEMA.INNODB_TABLESPACES 表在 MySQL 8.0.13 中引入,包括一个可用于识别加密表空间的ENCRYPTION列。
mysql> SELECT SPACE, NAME, SPACE_TYPE, ENCRYPTION FROM INFORMATION_SCHEMA.INNODB_TABLESPACES
WHERE ENCRYPTION='Y'\G
*************************** 1. row ***************************
SPACE: 4294967294
NAME: mysql
SPACE_TYPE: General
ENCRYPTION: Y
*************************** 2. row ***************************
SPACE: 2
NAME: test/t1
SPACE_TYPE: Single
ENCRYPTION: Y
*************************** 3. row ***************************
SPACE: 3
NAME: ts1
SPACE_TYPE: General
ENCRYPTION: Y
在CREATE TABLE或 ALTER TABLE语句中指定ENCRYPTION选项时,将记录在INFORMATION_SCHEMA.TABLES的CREATE_OPTIONS列中 。可以查询此列以识别驻留在加密的独立表空间中的表。
mysql> SELECT TABLE_SCHEMA, TABLE_NAME, CREATE_OPTIONS FROM INFORMATION_SCHEMA.TABLES
WHERE CREATE_OPTIONS LIKE '%ENCRYPTION%';
+--------------+------------+----------------+
| TABLE_SCHEMA | TABLE_NAME | CREATE_OPTIONS |
+--------------+------------+----------------+
| test | t1 | ENCRYPTION="Y" |
+--------------+------------+----------------+
查询
INFORMATION_SCHEMA.INNODB_TABLESPACES 以检索有关与特定模式和表关联的表空间的信息。
mysql> SELECT SPACE, NAME, SPACE_TYPE FROM INFORMATION_SCHEMA.INNODB_TABLESPACES WHERE NAME='test/t1';
+-------+---------+------------+
| SPACE | NAME | SPACE_TYPE |
+-------+---------+------------+
| 3 | test/t1 | Single |
+-------+---------+------------+
您可以通过查询
INFORMATION_SCHEMA.SCHEMATA表来识别启用加密的架构 。
mysql> SELECT SCHEMA_NAME, DEFAULT_ENCRYPTION FROM INFORMATION_SCHEMA.SCHEMATA
WHERE DEFAULT_ENCRYPTION='YES';
+-------------+--------------------+
| SCHEMA_NAME | DEFAULT_ENCRYPTION |
+-------------+--------------------+
| test | YES |
+-------------+--------------------+
SHOW CREATE SCHEMA还显示DEFAULT ENCRYPTION子句。
加密使用说明
1、使用ENCRYPTION选项更改现有的独立表空间时需进行适当的计划。驻留在独立表空间中的表会被使用COPY算法重建。INPLACE算法用于更改通用表空间或mysql系统表空间的ENCRYPTION属性。INPLACE算法允许对驻留在通用表空间中的表进行并发 DML。并发 DDL 会被阻止。
2、当一个通用表空间或mysql 系统表空间被加密时,驻留在该表空间中的所有表都被加密。同样,在加密表空间中创建的表也会被加密。
3、如果服务器在正常运行期间退出或停止,建议使用之前配置的相同加密设置重新启动服务器。
4、当第一个新的或现有的表空间被加密时,会生成第一个主加密密钥。
5、主密钥轮换会重新加密表空间密钥,但不会更改表空间密钥本身。要更改表空间密钥,您必须禁用并重新启用加密。对于独立表空间,重新加密表空间会导致 ALGORITHM=COPY重建表的操作。对于通用表空间和 mysql系统表空间,它是一个 ALGORITHM=INPLACE操作,不需要重建驻留在表空间中的表。
6、如果同时使用COMPRESSION 和ENCRYPTION 选项创建表 ,则在加密表空间数据之前执行压缩。
7、如果密钥环数据文件为空或丢失,则第一次执行 ALTER INSTANCE ROTATE INNODB MASTER KEY时创建主加密密钥。
8、卸载component_keyring_file或
component_keyring_encrypted_file组件不会删除现有的密钥环数据文件。卸载keyring_file或keyring_encrypted_file插件不会删除现有的密钥环数据文件。
9、建议您不要将密钥环数据文件放在与表空间数据文件相同的目录下。
10、在运行时或重新启动服务器时修改 keyring_file_data或
keyring_encrypted_file_data 设置可能会导致以前加密的表空间变得不可访问,从而导致数据丢失。
11、InnoDB 添加FULLTEXT索引时隐式创建FULLTEXT的索引表支持加密。
加密限制
1、高级加密标准 (AES) 是唯一受支持的加密算法。InnoDB表空间加密使用电子密码本 (ECB) 块加密模式进行表空间密钥加密,使用密码块链接 (CBC) 块加密模式进行数据加密。填充不与 CBC 块加密模式一起使用。相反, InnoDB确保要加密的文本是块大小的倍数。
2、仅对独立表空间、 通用表空间和mysql系统表空间支持加密 。MySQL 8.0.13 中引入了对通用表空间的加密支持。mysql从 MySQL 8.0.16 开始提供对系统表空间的加密支持 。InnoDB 包括系统表空间在内的其他表空间类型不支持加密。
3、您不能将表从加密的独立表空间、 通用表空间或mysql系统表空间移动或复制到不支持加密的表空间类型。
4、您不能将表从加密的表空间移动或复制到未加密的表空间。但是,允许将表从未加密的表空间移动到加密的表空间。例如,您可以将表从未加密的独立或通用表空间移动或复制到加密的通用表空间。
5、默认情况下,表空间加密仅适用于表空间中的数据。重做日志和撤消日志数据可以通过启用 innodb_redo_log_encrypt和innodb_undo_log_encrypt加密。
6、不允许更改驻留在或以前驻留在加密表空间中的表的存储引擎。