お問い合わせ
03-5979-2701
PowerGres
PowerGres V9.1 体験記 戻る

第 3 回 データを暗号化してみよう

対象バージョン: PowerGres Plus V9.1
本文では CentOS 5 (64 ビット版) において PowerGres Plus V9.1(Linux 版)を使用して解説しています。

今日では、企業や医療機関、自治体などの組織において、情報セキュリティ対策は慎重に取り扱うべき問題です。個人情報を収める場合もあるデータベースは、特に気を配る必要があります。

PostgreSQL は、クライアント認証とデータベースオブジェクトのアクセス制御によって、不正なユーザからデータベースのデータを保護しています。しかしながら、OS ファイルレベルでの暗号化はされておらず、ファイルやディスクの物理的な盗難に対しては対策が立てられていません。

そこで、第 3 回では、PostgreSQL の pgcrypto や、PowerGres Plus の独自機能である透過的データ暗号化を用いて、データベースの暗号化を行い、よりセキュアにデータベースを管理していく方法をご紹介します。

  1. PostgreSQL の pgcrypto による暗号化
    1. pgcrypto とは
    2. pgcrypto の設定方法
    3. テーブルデータの暗号化
    4. テーブルデータの復号
  2. PowerGres Plus の透過的データ暗号化
    1. 透過的データ暗号化とは
    2. 透過的データ暗号化の設定
    3. データの挿入・ファイルが暗号化済みであることの確認
  3. 透過的データ暗号化を利用した場合と利用しない場合の性能比較
  4. まとめ

PostgreSQL の pgcrypto による暗号化

まずは PowerGres のベースとなっている PostgreSQL の機能を用いてデータの暗号化を行います。

pgcrypto とは

PostgreSQL 自体にもデータの暗号化を行う仕組みは用意されており、contrib モジュールの pgcrypto を利用します。pgcrypto はデーターベースをテーブルのカラム単位で暗号化 / 復号する、PostgreSQL 用の関数群です

pgcrypto の設定方法

まずは pgcrypto が使えるようにします。ここでは、データベースの所有者を testuser とした、cryptodb を作成し、pgcrypto を使っていくことにします。第 1 回の記事を参考にデータベースのセットアップを行い、データベースユーザ testuser の作成と、データベース cryptodb の作成を完了しておいてください。

pgcrypto

psql で cryptodb に接続し、CREATE EXTENSION コマンドを実行します。CREATE EXTENSION コマンドはデータベースのスーパーユーザでなければいけません。

\c cryptodb
CREATE EXTENTION pgcrypto;
pgcrypto

暗号化で利用する鍵を、GnuPG を用いて作成します。新しい鍵ペアを作成しましょう。鍵の種類は DSA と Elgamal を指定します。

[postgres@node1 ~]$ gpg --gen-key
:
:
ご希望の鍵の種類を選択してください:
   (1) DSAとElgamal (既定)
   (2) DSA (署名のみ)
   (5) RSA (署名のみ)
選択は? 1 # デフォルトを指定
DSA keypair will have 1024 bits.
ELG-E keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 2048 # デフォルトを指定
要求された鍵長は2048ビット
鍵の有効期限を指定してください。
         0 = 鍵は無期限
      <n>  = 鍵は n 日間で満了
      <n>w = 鍵は n 週間で満了
      <n>m = 鍵は n か月間で満了
      <n>y = 鍵は n 年間で満了
鍵の有効期間は? (0)0 # 無期限を指定
Key does not expire at all
これで正しいですか? (y/N) y
:
:
本名: postgres
電子メール・アドレス: postgres@node1
コメント: # コメントは省略
:
:
名前(N)、コメント(C)、電子メール(E)の変更、またはOK(O)か終了(Q)? O
秘密鍵を保護するためにパスフレーズがいります。
# パスフレーズは省略
:
:
公開鍵と秘密鍵を作成し、署名しました。

ASCII アーマー形式で公開鍵と秘密鍵をエクスポートします。鍵ペアが複数ある場合は、--export オプションと --export-secret-keys オプションの後に使用する 鍵 ID を指定してください。

[postgres@node1 ~]$ gpg -a -o public.key --export
[postgres@node1 ~]$ gpg -a -o secret.key --export-secret-keys

鍵ペアの値を格納する gpgkey テーブルを作成します。psql で cryptodb に接続し、 testuser に変わります。鍵ペアの値は psql の変数に読み込ませて、INSERT 文で挿入します。

SET ROLE testuser;
CREATE TABLE gpgkey(public text, secret text);
\set PUBLIC `cat /var/lib/pgsql/public.key`
\set SECRET `cat /var/lib/pgsql/secret.key`
INSERT INTO gpgkey VALUES (:'PUBLIC', :'SECRET');

pgcrypto

ID と氏名から構成される usertbl テーブルを作成します。暗号化するカラムのデータ型は bytea 型にする必要があります。name カラムを bytea 型にしましょう。

CREATE TABLE usertbl(
id int,       --ID
name bytea    -- 氏名
);
pgcrypto

テーブルデータの暗号化

usertbl テーブルに、name カラムのデータを暗号化して挿入します。暗号化には pgp_pub_encrypt() 関数を使います。pgp_pub_encrypt() 関数は、第一引数に暗号化したいカラム名、第二引数に公開鍵を指定します。第三引数には使用する暗号アルゴリズムや圧縮アルゴリズムなどを指定できますが、ここではデフォルトのままとします。公開鍵の値は ASCII アーマー形式の文字列になっているので、dearmor() 関数を使ってバイナリ形式に戻す必要があります。

INSERT 文を使って、データを挿入してみましょう。

INSERT INTO usertbl VALUES (
1501,
pgp_pub_encrypt('TOKUGAWA Ieyasu', dearmor((SELECT public FROM gpgkey)))
);
INSERT INTO usertbl VALUES (
1502,
pgp_pub_encrypt('TOKUGAWA Hidetada', dearmor((SELECT public FROM gpgkey)))
);
INSERT INTO usertbl VALUES (
1503,
pgp_pub_encrypt('TOKUGAWA Iemitsu', dearmor((SELECT public FROM gpgkey)))
);

pgcrypto

usertbl テーブルの中身を確認してみましょう。投入したデータが暗号化されています。

\x
SELECT name FROM usertbl;
pgcrypto

テーブルデータの復号

usertbl テーブルのデータを復号して取り出します。復号には pgp_pub_decrypt() 関数を使います。pgp_pub_decrypt() 関数は、第一引数に復号したいカラム名、第二引数に秘密鍵を指定します。第三引数は、鍵ペアを作成したときにパスフレーズを指定します。パスフレーズを指定しなかった場合は空文字を指定します。秘密鍵の値も ASCII アーマー形式の文字列になっているので、dearmor() 関数を使ってバイナリ形式に戻す必要があります

usertbl テーブルを検索してみましょう。

\x
SELECT id, pgp_pub_decrypt(name, dearmor((SELECT secret FROM gpgkey)), '') AS name FROM usertbl;

pgcrypto

データを取得することができました。

PowerGres Plus の透過的データ暗号化

続いては、PowerGres Plus の独自機能による透過的データ暗号化によって、データの暗号化を行っていきます。

透過的データ暗号化とは

透過的データ暗号化は PostgreSQL の 暗号化したい列を指定する pgcypto とは異なり、指定したテーブル空間内の全てのユーザデータを暗号化します。暗号化されたテーブルやインデックスに対する操作によって出力されるトランザクションログや一時ファイルも自動的に暗号化されます。したがって、クライアント側は暗号化キーの管理や暗号化 / 復号の処理を気にする必要はありません。また、物理コピーによるバックアップデータも、暗号化されたデータは暗号化されたままとなっています。

透過的データ暗号化

透過的データ暗号化では、二層のキーストアファイルによってデータを保護しています。暗号化されたテーブル空間には、その中の全てのデータを暗号化 / 復号するキーストアファイルがあります。このキーストアファイルはデータベースクラスタに 1 つだけ作成されるマスター暗号化キーによって暗号化されています。マスター暗号化キーは DB 管理者が指定したパスフレーズに基づいて暗号化され、キーストアファイルに保存されます。

透過的データ暗号化の設定

それでは透過的データ暗号化を設定してみましょう。

はじめに、マスター暗号化キーの設定を行います。管理ツールを起動し、「データ暗号化」の「キーストア格納ディレクトリ」にキーストアファイルを格納するディレクトリを指定し、「適用(A)」ボタンをクリックします。サービスの再起動を促されるのでサービスを再起動します。

透過的データ暗号化

サービスを再起動したら、「マスター暗号化キーを作成」ボタンをクリックしてキーストアファイルをオープンする際に使用するパスフレーズを入力してください。マスター暗号化キーはこのパスフレーズで保護されるので、単純で推測されやすい文字列は指定しないようにしてください。また、ここで指定したパスフレーズを忘れてしまうと、暗号化されたデータには二度とアクセスできなくなります。パスフレーズは忘れないようにしてください。

透過的データ暗号化

透過的データ暗号化を利用する際は、作成したキーストアファイルをオープンしておく必要があります。サービスの起動に合わせて自動的にキーストアがオープンされるようにしておきましょう。「キーストアの自動オープンを有効にする」をクリックしてパスフレーズを入力します。

透過的データ暗号化

暗号化用のテーブル空間を作成します。「オブジェクト」の「テーブルスペース」の「テーブルスペースを作成」ボタンをクリックします。

以下の設定を入力します。

設定項目 設定値
テーブルスペース名 tde-space
テーブルスペースの場所 /var/lib/pgsql/tde
テーブルスペースの所有者 postgres
データ暗号化アルゴリズム AES128
透過的データ暗号化

データの挿入・ファイルが暗号化済みであることの確認

暗号化したテーブル空間にデータベースを作成し、データを挿入していきます。これらの手順は、透過的データ暗号化を利用しない場合と何も変わりはありません。

「オブジェクト」の「データベース」にある「データベースを作成」ボタンをクリックし、以下の設定でデータベースを作成します。

設定項目 設定値
データベース名 tdedb
データベース所有者 testuser
文字エンコーディング UTF8
テーブルスペース tde-space
透過的データ暗号化

psql で tdedb に接続し、testuser に代わって pgcrypto と同様のテーブルを作成します。INSERT 文でデータを挿入し、SELECT 文で確認します。SQL 文やテーブル定義を書き換えることなく暗号化 / 復号は行われます。

\c tdedb
SET ROLE testuser;
CREATE TABLE usertbl(
id int,
name text
);
INSERT INTO usertbl VALUES (1504, 'TOKUGAWA Ietsuna');
INSERT INTO usertbl VALUES (1505, 'TOKUGAWA Tsunayoshi');
INSERT INTO usertbl VALUES (1506, 'TOKUGAWA Ienobu');
SELECT * FROM usertbl;

透過的データ暗号化

テーブルデータが格納されているファイルを確認してみましょう。PostgreSQL の組み込み関数である pg_relation_filepath() でテーブルデータが格納されているファイルパスを特定し、ファイルを読み込みます。

SELECT pg_relation_filepath('usertbl');
透過的データ暗号化

usertbl の中身です。入力した氏名は暗号化されており、特定することができません。

透過的データ暗号化

こちらは、usertbl テーブルと同一のデータを暗号化せずに挿入したテーブルの中身です。氏名が特定できてしまっています。

透過的データ暗号化

透過的データ暗号化を利用した場合と利用しない場合の性能比較

透過的データ暗号化の特徴的な利点は、クライアント側が暗号化キーの管理や、暗号化 / 復号の処理を意識する必要がないだけではありません。

オーバーヘッドが少ない

透過的データ暗号化は、ディスク I/O が発生するときのみ、暗号化 / 復号が行われます。バッファ・キャッシュ内のデータアクセスの際は暗号化を行わないのでオーバーヘッドはありません。また、Intel Xeon プロセッサの 5600 番台以降に搭載された AES-NI を用いた場合、暗号化 / 復号のオーバヘッドは極消化されます。

具体的な暗号化、非暗号化時の性能比較結果を以下に掲載します。

測定方法

以下の条件で OLTP、バッチ処理、ロードの性能を測定しました。

測定環境

ハードウェア FUJITSU PRIMERGY RX300 S7
CPU: Intel Xeon E5-2690 2.90GHz(8コア)×2
DRAM: 160GB
ストレージ: SSD(PCI Express)
ソフトウェア OS: Red Hat Enterprise Linux 6.2(64ビット)
RDBMS: PowerGres Plus V9.1(64ビット)

結果

それぞれの結果をグラフに示します。

性能検証

はじめは pgbench の実行結果です。1 秒あたりのトランザクション数 (TPS) は暗号化、非暗号化の間に差はありません。また、暗号化した場合であっても、暗号化強度、AES-NIの有無による TPS の差はありません。

性能検証
性能検証

バッチ処理およびロード処理性能の測定結果は同様の傾向が示されました。どちらの測定結果も、処理時間は暗号化したほうが増加しています。しかし、AES-NI を有効にした場合は増加量は抑えられています。

以上の結果から、ディスクアクセスが少ない OLTP では暗号化のオーバヘッドはほとんどなく、ディスクアクセスの多いバッチ処理やロードにおいても、AES-NI が有効であれば暗号化のオーバーヘッドはほぼ抑えられており、透過的データ暗号化のオーバヘッドは非常に小さいと言えます。

まとめ

今回は PowerGres Plus の透過的データ暗号化機能についての解説でした。透過的データ暗号化は、クライアント側が暗号化 / 復号を意識することなく手軽に使えるメリットがあります。また、オーバヘッドもほとんどありません。PowerGres Plus を使って、手軽な GUI でセキュアな DB 管理をぜひともお試しください。