Oracleで暗号化に関する検証 その1

投稿日: 2005年11月16日

<Oracleで暗号化に関する検証 その1>
ペンネーム:ウィーット

今回から、Oracleを用いての暗号化について検証していきたいと思います。

個人情報保護法やSOX法などの策定が進んでいる中、企業におけるシステムの
セキュリティに注目が集まってきています。
DBにもセキュリティ機能が追加されていますが、Oracleで実現する暗号化につ
いて検証してみたいと思います。

まずは、Oracle10gR2 Enterprise Editionの新機能である「透過的なデータ暗
号化(Transparent Data Encryption 略してTDE)」について検証します。

TDEの特徴は以下の通りです。
・DB全体(Oracle)で共通鍵を生成・維持するため、ユーザーは鍵の管理を行わ
なくてよい
(OS上に鍵が作成されるため、その管理はユーザーが行わなくてはいけない)
・アプリケーションの変更なしで既存のテーブルに暗号化を行うことができる
・暗号化してある項目に索引をつけられる

新規テーブルに対して暗号化の項目を作成する手順と、既存のテーブルに暗号
化を行う手順を行ってみます。

まず準備として共通鍵の作成が必要です。
作成は、以下の手順で行います。

(1)sqlnet.oraに共通鍵の作成場所を指定する。
(2)リスナーを再起動する。
(3)SYSユーザーで鍵(Wallet)を作成する。
(4)dbms_crypto 権限を使用ユーザーに付与する。

テスト環境は以下の通りです。
Red Hat Enterprise Linux AS release 3 (Taroon Update 1)
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0

それでは始めましょう。

(1) sqlnet.oraに共通鍵の作成場所を指定します。
$ORACLE_HOME/network/admin/sqlnet.oraに共通鍵の場所を指定します。

ENCRYPTION_WALLET_LOCATION=
        (SOURCE=(METHOD=FILE)(METHOD_DATA=
        (DIRECTORY=/home/ora102/oracle/oracle/product/10.2.0/db_1)))
                                ↑
                         鍵を生成するディレクトリを指定

上記を指定しない場合は、以下のディレクトリ配下に作成されます。
$ORACLE_BASE/admin/$ORACLE_SID/wallet

(2) リスナーの再起動を行います。

(3) 鍵を生成します。

conn / as sysdba

SQL> alter system set encryption key identified by "xxxxx";

「xxxxx」にパスワードを指定します。

鍵は、sqlnet.oraに指定したディレクトリに「ewallet.p12」という名前で作
成されます。

(4) dbms_crypto 権限を使用ユーザーに付与します。

SQL> grant execute on dbms_crypto to scott;

Grant succeeded.

ようやく環境が整いました。フー!

TDEを使用する環境が整ったので、新規にテーブルを作成する場合と既存のテー
ブルに暗号化を行ってみます。

それでは、新規にテーブルを作成してみましょう。
テーブル名は「emp_encrypt」とします。

SQL> create table emp_encrypt (
        empno   number(4) not null,
        ename   varchar2(10),
        job             varchar2(9),
        mgr             number(4),
        hiredate        date,
        sal             number(7,2) encrypt not null,
        comm    number(7,2),
        deptno  number(2)
) tablespace encrypt;

表が作成されました。

暗号化する項目に対して「encrypt」を指定します。

次に、暗号化している「sal」の項目に対してインデックスを作成してみましょう。

**********************************************************************

SQL> create index idx_emp_encrypt on scott.emp_encrypt (sal);
create index idx_emp_encrypt on scott.emp_encrypt (sal)
                                                   *
行1でエラーが発生しました。:
ORA-28338: 索引付けされた列は、saltを使用して暗号化できません

**********************************************************************

お、エラーが出力されました。saltというのは乱数を生成して暗号化対象のデー
タを一定のビット長に補正(パディング)し、暗号化を行えるようにする機能で
す。暗号化の単位となるブロック長に満たない場合は、一定以上の長さを持つ
乱数で補正をしているようです。
この乱数(salt)指定があるとインデックスの作成が出来ないようです。

暗号化をする際に、乱数を付加されないように変更してみます。
新規に作成する時には、「no salt」オプションとして再度作成してみましょう。

**********************************************************************

SQL> create table emp_encrypt (
        empno   number(4) not null,
        ename   varchar2(10),
        job             varchar2(9),
        mgr             number(4),
        hiredate        date,
        sal             number(7,2) encrypt no salt not null,
        comm    number(7,2),
        deptno  number(2)
) tablespace encrypt;
  2    3    4    5    6    7    8    9   10
表が作成されました。

SQL> create index idx_emp_encrypt on scott.emp_encrypt (sal);

索引が作成されました。

**********************************************************************

既存のテーブルへの暗号化は以下のコマンドで実行します。

**********************************************************************
alter table 対象テーブル名(項目名 encyrpt); <—- インデックスを作
成しない場合
alter table 対象テーブル名(項目名 encrypt no salt); <—- インデックス
を作成または
既存する場合
**********************************************************************

既にインデックスがあり、no saltオプションを指定しない場合、以下のエラー
が出力されます。

**********************************************************************

行1でエラーが発生しました。:
ORA-28338: 索引付けされた列は、saltを使用して暗号化できません

**********************************************************************

乱数(salt)オプションについては、USER_ENCRYPTED_COLUMNSビューのSALの項目
を参照します。

**********************************************************************

SQL> select * from USER_ENCRYPTED_COLUMNS where TABLE_NAME='EMP_ENCRYPT';

TABLE_NAME                COLUMN_NAME               ENCRYPTION_ALG           SAL
------------------------- ------------------------- ------------------------ ---
EMP_ENCRYPT               SAL                       AES 192 bits key         YES

**********************************************************************

暗号化された項目に紐付けられたインデックスが本当に使用されているのか
SQL_TRACEから確認をしてみましょう。

**********************************************************************

SQL> select * from emp_encrypt where sal = 1600;

**********************************************************************

このSQLの実行結果です。

**********************************************************************

実行計画
-------  ---------------------------------------------------
      0  SELECT STATEMENT   MODE: ALL_ROWS
      1   TABLE ACCESS   MODE: ANALYZED (BY INDEX ROWID) OF 'EMP_ENCRYPT'
              (TABLE)
      0    INDEX   MODE: ANALYZED (RANGE SCAN) OF 'IDX_EMP_ENCRYPT'
               (INDEX)

**********************************************************************

インデックスが正しく使われていることがわかりました。
(統計情報の取得を行っております。)

鍵を使用停止(close)して、検索をしてみましょう。

**********************************************************************

SQL> conn / as sysdba
接続されました。
SQL> alter system set wallet close;

システムが変更されました。

SQL> conn scott/tiger
接続されました。

SQL> select * from emp_encrypt where EMPNO = 7499;
select * from emp_encrypt where EMPNO = 7499
              *
行1でエラーが発生しました。:
ORA-28365: ウォレットがオープンしていません

**********************************************************************

それでは、暗号化をしていない項目だけの検索は出来るでしょうか?

**********************************************************************

SQL> select EMPNO,ENAME,JOB,MGR,HIREDATE,COMM,DEPTNO from emp_encrypt
  2  where empno = 7499;

 EMPNO ENAME      JOB              MGR HIREDATE       COMM     DEPTNO
------ ---------- --------- ---------- -------- ---------- ----------
  7499 ALLEN      SALESMAN        7698 81-02-20        300         30

**********************************************************************

暗号化機能を使用するには、Walletをopenします。

**********************************************************************

SQL> conn / as sysdba
接続されました。

SQL> alter system set wallet open identified by "xxxxx";

システムが変更されました。

SQL> conn scott/tiger
接続されました。

SQL> select * from emp_encrypt where sal = 1600;

 EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
------ ---------- --------- ---------- -------- ---------- ---------- ----------
  7499 ALLEN      SALESMAN        7698 81-02-20       1600        300         30

**********************************************************************

おおお、出来ました。
暗号化された項目の表示には、「Wallet」がOPENされていないと駄目なようで
す。

次週は、既存のテーブルに暗号化項目を追加したときのパフォーマンスの測定
とExport/Importについて検証をしてみたいと思います。

秋を実感しつつある茅ヶ崎にて