InnoDB / XtraDB Enabling Encryption
Contents
In order to enable data-at-rest encryption for tables using the InnoDB or XtraDB storage engines, you first need to configure the Server to use an Encryption Key Management plugin. Once this is done, you can enable encryption by setting the innodb_encrypt_tables
system variable to encrypt the InnoDB system and file tablespaces and setting the innodb_encrypt_log
system variable to encrypt the InnoDB Redo Log.
Setting these system variables enables the encryption feature for InnoDB and XtraDB tables on your server. To use the feature, you need to use the ENCRYPTION_KEY_ID
table option to set what encryption key you want to use and set the ENCRYPTED
table option to enable encryption.
When encrypting any InnoDB or XtraDB tables, the best practice is also enable encryption for the Redo Log. If you have encrypted InnoDB tables and have not encrypted the Redo Log, data written to an encrypted table may be found unencrypted in the Redo Log.
Enabling Encryption for Automatically Encrypted Tablespaces
The innodb_encrypt_tables
system variable controls the configuration of automatic encryption of InnoDB tables. It has the following possible values:
Option | Description |
---|---|
OFF | Disables table encryption. |
ON | Enables table encryption, but allows unencrypted tables to be created. |
FORCE | Enables table encryption, and doesn't allow unencrypted tables to be created. Added in MariaDB 10.1.4. |
When innodb_encrypt_tables
is set to ON
, InnoDB tables are automatically encrypted by default. For example, the following statements create an encrypted table and confirm that it is encrypted:
SET GLOBAL innodb_encryption_threads=4; SET GLOBAL innodb_encrypt_tables=ON; SET SESSION innodb_default_encryption_key_id=100; CREATE TABLE tab1 ( id int PRIMARY KEY, str varchar(50) ); SELECT NAME, ENCRYPTION_SCHEME, CURRENT_KEY_ID FROM information_schema.INNODB_TABLESPACES_ENCRYPTION WHERE NAME='db1/tab1'; +----------+-------------------+----------------+ | NAME | ENCRYPTION_SCHEME | CURRENT_KEY_ID | +----------+-------------------+----------------+ | db1/tab1 | 1 | 100 | +----------+-------------------+----------------+
When innodb_encrypt_tables
is set to ON
, an unencrypted InnoDB table can be created by setting the ENCRYPTED
table option to NO
for the table. For example, the following statements create an unencrypted table and confirm that it is not encrypted:
SET GLOBAL innodb_encryption_threads=4; SET GLOBAL innodb_encrypt_tables=ON; SET SESSION innodb_default_encryption_key_id=100; CREATE TABLE tab1 ( id int PRIMARY KEY, str varchar(50) ) ENCRYPTED=NO; SELECT NAME, ENCRYPTION_SCHEME, CURRENT_KEY_ID FROM information_schema.INNODB_TABLESPACES_ENCRYPTION WHERE NAME='db1/tab1'; +----------+-------------------+----------------+ | NAME | ENCRYPTION_SCHEME | CURRENT_KEY_ID | +----------+-------------------+----------------+ | db1/tab1 | 0 | 100 | +----------+-------------------+----------------+
When innodb_encrypt_tables
is set to FORCE
, InnoDB tables are automatically encrypted by default, and unencrypted InnoDB tables can not be created. In this scenario, if you set the ENCRYPTED
table option to NO
for a table, then you will encounter an error. For example:
SET GLOBAL innodb_encryption_threads=4; SET GLOBAL innodb_encrypt_tables='FORCE'; SET SESSION innodb_default_encryption_key_id=100; CREATE TABLE tab1 ( id int PRIMARY KEY, str varchar(50) ) ENCRYPTED=NO; ERROR 1005 (HY000): Can't create table `db1`.`tab1` (errno: 140 "Wrong create options") SHOW WARNINGS; +---------+------+----------------------------------------------------------------------+ | Level | Code | Message | +---------+------+----------------------------------------------------------------------+ | Warning | 140 | InnoDB: ENCRYPTED=NO implies ENCRYPTION_KEY_ID=1 | | Warning | 140 | InnoDB: ENCRYPTED=NO cannot be used with innodb_encrypt_tables=FORCE | | Error | 1005 | Can't create table `db1`.`tab1` (errno: 140 "Wrong create options") | | Warning | 1030 | Got error 140 "Wrong create options" from storage engine InnoDB | +---------+------+----------------------------------------------------------------------+ 4 rows in set (0.00 sec)
When innodb_encrypt_tables
is set to ON
or FORCE
, then you must ensure that innodb_encryption_threads
is set to a non-zero value, so that InnoDB can perform any necessary encryption operations in the background. See background operations for more information about that. innodb_encryption_rotate_key_age
must also be set to a non-zero value for the initial encryption operations to happen in the background. See disabling key rotations for more information about that.
Enabling Encryption for Manually Encrypted Tablespaces
If you do not want to automatically encrypt every InnoDB table, then it is possible to manually enable encryption for just the subset of InnoDB tables that you would like to encrypt. MariaDB provides the ENCRYPTED
and ENCRYPTION_KEY_ID
table options that can be used to manually enable encryption for specific InnoDB tables. These table options can be used with CREATE TABLE
and ALTER TABLE
statements. These table options can only be used with InnoDB tables that have their own InnoDB's file-per-table tablespaces, meaning that tables that were created with innodb_file_per_table=ON
set.
Table Option | Value | Description |
---|---|---|
ENCRYPTED | Boolean | Defines whether to encrypt the table |
ENCRYPTION_KEY_ID | 32-bit integer | Defines the identifier for the encryption key to use |
You can manually enable or disable encryption for a table by using the ENCRYPTED
table option. If you only need to protect a subset of InnoDB tables with encryption, then it can be a good idea to manually encrypt each table that needs the extra protection, rather than encrypting all InnoDB tables globally with innodb_encrypt_tables
. This allows you to balance security with speed, as it means the encryption and decryption performance overhead only applies to those tables that require the additional security.
If a manually encrypted InnoDB table contains a FULLTEXT INDEX, then the internal table for the full-text index will not also be manually encrypted. To encrypt internal tables for InnoDB full-text indexes, you must enable automatic InnoDB encryption by setting innodb_encrypt_tables
to ON
or FORCE
.
You can also manually specify a encryption key for a table by using the ENCRYPTION_KEY_ID
table option. This allows you to use different encryption keys for different tables. For example, you might create a table using a statement like this:
CREATE TABLE tab1 ( id int PRIMARY KEY, str varchar(50) ) ENCRYPTED=YES ENCRYPTION_KEY_ID=100; SELECT NAME, ENCRYPTION_SCHEME, CURRENT_KEY_ID FROM information_schema.INNODB_TABLESPACES_ENCRYPTION WHERE NAME='db1/tab1'; +----------+-------------------+----------------+ | NAME | ENCRYPTION_SCHEME | CURRENT_KEY_ID | +----------+-------------------+----------------+ | db1/tab1 | 1 | 100 | +----------+-------------------+----------------+
If the ENCRYPTION_KEY_ID
table option is not specified, then the table will be encrypted with the key identified by the innodb_default_encryption_key_id
system variable. For example, you might create a table using a statement like this:
SET SESSION innodb_default_encryption_key_id=100; CREATE TABLE tab1 ( id int PRIMARY KEY, str varchar(50) ) ENCRYPTED=YES; SELECT NAME, ENCRYPTION_SCHEME, CURRENT_KEY_ID FROM information_schema.INNODB_TABLESPACES_ENCRYPTION WHERE NAME='db1/tab1'; +----------+-------------------+----------------+ | NAME | ENCRYPTION_SCHEME | CURRENT_KEY_ID | +----------+-------------------+----------------+ | db1/tab1 | 1 | 100 | +----------+-------------------+----------------+
In the event that you have an existing table and you want to manually enable encryption for that table, then you can do the same with an ALTER TABLE
statement. For example:
CREATE TABLE tab1 ( id int PRIMARY KEY, str varchar(50) ) ENCRYPTED=NO; SELECT NAME, ENCRYPTION_SCHEME, CURRENT_KEY_ID FROM information_schema.INNODB_TABLESPACES_ENCRYPTION WHERE NAME='db1/tab1'; +----------+-------------------+----------------+ | NAME | ENCRYPTION_SCHEME | CURRENT_KEY_ID | +----------+-------------------+----------------+ | db1/tab1 | 0 | 100 | +----------+-------------------+----------------+ ALTER TABLE tab1 ENCRYPTED=YES ENCRYPTION_KEY_ID=100; SELECT NAME, ENCRYPTION_SCHEME, CURRENT_KEY_ID FROM information_schema.INNODB_TABLESPACES_ENCRYPTION WHERE NAME='db1/tab1'; +----------+-------------------+----------------+ | NAME | ENCRYPTION_SCHEME | CURRENT_KEY_ID | +----------+-------------------+----------------+ | db1/tab1 | 1 | 100 | +----------+-------------------+----------------+
InnoDB and XtraDB do not permit manual encryption changes to tables in the system tablespace using ALTER TABLE
. Encryption of the system tablespace can only be configured by setting the value of the innodb_encrypt_tables
system variable. This means that when you want to encrypt or decrypt the system tablespace, you must also set a non-zero value for the innodb_encryption_threads
system variable, and you must also set the innodb_system_rotate_key_age
system variable to 1
to ensure that the system tablespace is properly encrypted or decrypted by the background threads. See MDEV-14398 for more information.
Enabling Encryption for Temporary Tablespaces
The innodb_encrypt_temporary_tables
system variable controls the configuration of encryption for the temporary tablespace. It has the following possible values:
Option | Description |
---|---|
OFF | Disables temporary table encryption. |
ON | Enables temporary table encryption. |
This system variable can be specified as a command-line argument to mysqld
or it can be specified in a relevant server option group in an option file. For example:
[mariadb] ... innodb_encrypt_temporary_tables=ON
Enabling Encryption for the Redo Log
InnoDB uses the Redo Log in crash recovery. By default, these events are written to file in an unencrypted state. In configuring MariaDB for data-at-rest encryption, ensure that you also enable encryption for the Redo Log.
To encrypt the Redo Log, first stop the server process. Then, set the innodb_encrypt_log
to ON
in a relevant server option group in an option file. For example:
[mariadb] ... innodb_encrypt_log = ON
Then, start MariaDB. When the server starts back up, it checks to recover InnoDB in the event of a crash. Once it is back online, it begins writing encrypted data to the Redo Log.
In MariaDB 10.3 and before, InnoDB does not support key rotation for the Redo Log. Key rotation for the Redo Log is supported in MariaDB 10.4 and later. See InnoDB / XtraDB Encryption Keys: Key Rotation for more information.