5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

無料で行うOracle Database の暗号化を簡単に使う方法

Last updated at Posted at 2022-11-04

概要

Oracle Databaseで暗号化を行う場合、様々な方法があります。
その中でも無料で利用可能なものとして、DBMS_CRYPTO というパッケージがあります。

これを利用してみたところ、なかなかに使い方が面倒くさいことが分かったので、この記事ではDBMS_CRYPTOを使いやすくするファンクションのコードを紹介します。

暗号化/復号化の利用イメージ

DBMS_CRYPTOは暗号化や復号化が出来るということなので、以下のようにできるのかなぁ?と思ったけど、どうやら違うようだ。

 以下は動作しません
insert into employee_card(id,cardnumber) values (100001, DBMS_CRYPTO.ENCRYPT('123456789012'));
select id from employee_card where cardnumber = DBMS_CRYPTO.ENCRYPT('123456789012');
select DBMS_CRYPTO.DECRYPT(cardnumber) from employee_card where id = 100001;

実際は結構面倒なことをしないといけないらしい。
ただ、暗号化するアプリごとにそれを実装するのは超めんどい。。

なので、上記のように動作するようなファンクションを作ってしまえば良いのでは?と思い、DBUP_CRYPTOを作成しました。

前提条件

Oracle Database 19.15.0で検証しています。
また、暗号化のアルゴリズムなどは以下を選択しています。

設定項目 設定内容 コマンド
暗号化アルゴリズム AES 128bit ENCRYPT_AES128
ブロック暗号連鎖 暗号ブロック連鎖 CHAIN_CBC
ブロック暗号パディング PKCS#5 PAD_PKCS5
初期化ベクター null null

この辺りの詳細情報は以下公式マニュアルをご参照ください。
PL/SQLパッケージおよびタイプ・リファレンス - 42 DBMS_CRYPTO

なお、暗号化鍵情報はDBの中に格納しておいた方が安心な気がしたので、encユーザーを作り、そこにenctabというテーブルを作ってその中に格納することにしています。

事前準備

鍵とかを事前に作る必要があるので、以下を行う

  • 管理者権限のユーザーでencユーザーを作成し、鍵の値を入れるテーブルを作成して鍵の値を入力する
SQL> create user enc identified by ***** quota unlimited on users;
SQL> create table enc.enctab (enckey char(16));
SQL> insert into enc.enctab values ('1234567890123456');
SQL> commit;
  • encユーザーにDBMS_CRYPTOの実行権限を付与する
SQL> grant execute on dbms_crypto to enc;
  • パッケージを管理者権限のユーザーでインストールする
    (この手順でencユーザーにdbup_cryptoが作成される)
SQL> @dbup_crypto.sql
  • 暗号化パッケージを利用するユーザーにインストールしたファンクションの権限を付与する
SQL> grant execute on enc.dbup_crypto to パッケージユーザー;

dbup_crypto.sqlのコード

create or replace package ENC.DBUP_CRYPTO 
as
  function encrypt (char_for_encryption in varchar2) return raw;
  function decrypt (char_for_decryption in raw) return varchar2;
  function readenqval return varchar2;
end;
/

create or replace package body ENC.DBUP_CRYPTO
is
    function readenqval return varchar2
    is
        v_data  varchar2(100);
    begin
        select enckey into v_data from ENC.ENCTAB where rownum < 2;
        return v_data;
    end readenqval;

    function encrypt (char_for_encryption in varchar2) return raw
    is
        v_myKey     varchar2(16);
        v_enctype   number := DBMS_CRYPTO.ENCRYPT_AES128 + DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_PKCS5;
        v_keyval    raw(16);
        v_encval    raw(2000);
    begin
        v_myKey := dbup_crypto.readenqval;
        v_keyval := UTL_I18N.STRING_TO_RAW(v_myKey, 'AL32UTF8');
        v_encval := UTL_I18N.STRING_TO_RAW(char_for_encryption, 'AL32UTF8');
        return dbms_crypto.encrypt(src => v_encval, typ => v_enctype, key => v_keyval, iv => null);
    end encrypt;

    function decrypt (char_for_decryption in raw) return varchar2
    is 
        v_myKey     varchar2(16);
        v_enctype   number := DBMS_CRYPTO.ENCRYPT_AES128 + DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_PKCS5;
        v_keyval    raw(16);
    begin
        v_myKey := dbup_crypto.readenqval;
        v_keyval :=  UTL_I18N.STRING_TO_RAW(v_myKey, 'AL32UTF8');
        return UTL_I18N.RAW_TO_CHAR(dbms_crypto.decrypt(src => char_for_decryption, typ => v_enctype, key => v_keyval, iv => null), 'AL32UTF8');
    end decrypt;

    end;
/

DBUP_CRYPTOの利用サンプル

まずは暗号化データを格納するテーブルを作る

SQL> create table employee_card (id number, cardnumber raw(100));

Table created.

続いて、123456789012というデータを暗号化してテーブルに入れてみる

SQL> insert into employee_card values (100001, enc.DBUP_CRYPTO.ENCRYPT('123456789012'));

1 row created.

SQL> select * from employee_card;

        ID CARDNUMBER
---------- -----------------------------------
    100001 7E9634826EE8B79227B43C8B6A29AE17 ★暗号化されている

暗号化された状態でテーブルに格納された!

暗号化したデータをキーにして検索が出来るかも確認する。

SQL> select id from employee_card where cardnumber = enc.DBUP_CRYPTO.ENCRYPT('123456789012');

        ID
----------
    100001

検索できた!

復号したデータがselect出来るか確認する

SQL> select enc.DBUP_CRYPTO.DECRYPT(cardnumber) from employee_card where id = 100001;

ENC.DBUP_CRYPTO.DECRYPT(CARDNUMBER)
-------------------------------------
123456789012 ★暗号化する前の情報が確認できる

正しく復号出来ることが確認できた!

#結果
dbms_cryptoは使い勝手が悪いと思っていたが、使い勝手を良くするファンクションを使って開発を捗らせることができた

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?