今仕事でMariaDBを使っているのだが、どうやらMariaDBにはテーブルを暗号化する機能があるらしい。
というわけで、こちらを参考に実際にやってみる事にした。

なお、すでにMariaDBはインストール済みで、プロセスは起動していない状態とする。
また、この機能はMariaDBの10.1.3以降でないと利用出来ないので、もしこれより前のバージョンを使用しているようであればアップデートが必要なので注意。
今回は、2016/02/12時点で最新版であるMariaDB 10.1.11を用いている。

1.鍵ファイルの作成

まずは、以下のコマンドでテーブルの暗号化をする鍵ファイル(とりあえずここではkey.txtとする)の中身を作成する。

openssl enc -aes-256-cbc -k パスワード -P -md sha1
[root@test-node ~]# openssl enc -aes-256-cbc -k Password1 -P -md sha1
salt=51C82DA044E0B1F1
key=F1FD7027872C000500DCF9D5FBBDFA624AF88551EA6D419C8922712FB85C97F7
iv =5D9E9DFEC73ACB0E1E4B17A1F058A7D2

上記コマンドの出力結果を元に、「key.txt」を以下の内容・記述で作成する。

暗号化・復号化する際の鍵番号;iv;key

上の例でいうと、以下のようにファイルを作成する。

[root@test-node ~]# cat /opt/key.txt
1;5D9E9DFEC73ACB0E1E4B17A1F058A7D2;F1FD7027872C000500DCF9D5FBBDFA624AF88551EA6D419C8922712FB85C97F7

「key.txt」を作成したら、さらにそれを暗号化した「key.enc」を以下のコマンドで作成する。

openssl enc -aes-256-cbc -md sha1 -k パスワード2 -in /opt/key.txt -out /opt/key.enc
[root@test-node ~]# openssl enc -aes-256-cbc -md sha1 -k Password2 -in /opt/key.txt -out /opt/key.enc
[root@test-node ~]# ls -la /opt/key.enc
-rw-r--r--. 1 root root 128  2月 12 10:55 /opt/key.enc
[root@test-node ~]# file /opt/key.enc
/opt/key.enc: data

2.設定ファイルの追記

鍵ファイルの作成ができたら、次はMariaDBの設定ファイル「/etc/my.cnf.d/server.cnf」へ、暗号化について設定を追記する。

[mysqld]
plugin-load-add=file_key_management.so
file_key_management
file_key_management_filename = /PATH/key.enc
file_key_management_filekey = パスワード2
file_key_management_encryption_algorithm=AES_CBC

今回、実際に設定した値がこちら。

[root@test-node ~]# grep -v ^# /etc/my.cnf.d/server.cnf

[server]

[mysqld]
plugin-load-add=file_key_management.so
file_key_management
file_key_management_filename = /opt/key.enc
file_key_management_filekey = Password2
file_key_management_encryption_algorithm=AES_CBC

[galera]

[embedded]

[mariadb]

[mariadb-10.1]

後は、以下のコマンドでMariaDBを起動するだけだ。

service mysql start

3.テーブルの作成

さて、それでは実際にテーブルを作成してみよう。
作り方は簡単で、以下のようにCREATE文に「ENCRYPTED=YES」、「ENCRYPTION_KEY_ID=カギ番号」を指定するだけだ。

CREATE TABLE TEST_ENCRIPTION(TEST_ID BIGINT NOT NULL PRIMARY KEY, TEST_VAR VARCHAR(80)) ENGINE=InnoDB ENCRYPTED=YES ENCRYPTION_KEY_ID=1;
MariaDB [test]> CREATE TABLE TEST_ENCRIPTION(TEST_ID BIGINT NOT NULL PRIMARY KEY, TEST_VAR VARCHAR(80)) ENGINE=InnoDB  ENCRYPTED=YES ENCRYPTION_KEY_ID=1;
Query OK, 0 rows affected (0.01 sec)
MariaDB [test]> INSERT INTO TEST_ENCRIPTION(TEST_VAR) VALUES("test");
Query OK, 1 row affected, 1 warning (0.00 sec)

MariaDB [test]> INSERT INTO TEST_ENCRIPTION(TEST_ID,TEST_VAR) VALUES(1,"test");
Query OK, 1 row affected (0.00 sec)

MariaDB [test]> SELECT * FROM TEST_ENCRIPTION;
+---------+----------+
| TEST_ID | TEST_VAR |
+---------+----------+
|       0 | test     |
|       1 | test     |
+---------+----------+
2 rows in set (0.00 sec)

これで、テーブルの暗号化が無事実施出来た。
実際にテーブルが暗号化されているか、以下のように確認してみよう。

strings テーブルファイル(ibdファイル)
[root@test-node ~]# strings /var/lib/mysql/test/TEST_ENCRIPTION.ibd
1_ie
_mek
xkOH
l|\
j!EEzD
G[5H
wBc[`
......

確かに、中身が読めないように暗号化されているようだ。
ちなみに、こちらは暗号化されていない状態のテーブル。stringsで中身がある程度見れてしまう。

[root@test-node ~]# strings /var/lib/mysql/test/TEST_NOT_ENCRIPTION.ibd
Y;)C
infimum
supremum
test
test

これで、鍵ファイルがない環境ではテーブルを読めないことになる。
なお、当たり前の話ではあるが、鍵ファイルを移動したり名前変えたり、中身が変わったりするとテーブルが読み込めなくなるので注意。
読めるべき環境で読めなくなっては元も子もない。ちゃんと鍵ファイルもバックアップしておこう。

MariaDB [test]> SELECT * FROM TEST_ENCRIPTION;
ERROR 1296 (HY000): Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB

今回はserver.cnfにパスワードを記述しているが、opensslコマンドで鍵ファイルで暗号化していればファイル指定でもいけるので、この辺は状況に合わせよう。
なお、既存のテーブルを暗号化する場合は、ALTER文でいける。

ALTER TABLE テーブル名 ENCRYPTED=YES ENCRYPTION_KEY_ID=鍵番号;