DBMS_CRYPTO 使用例 〜暗号化〜

暗号化 ENCRYPT および 復号化 DECRYPT

SQL 文からの DBMS_CRYPTO.ENCRYPT ファンクション

DBMS_CRYPTO パッケージ Oracle 10g には ENCRYPT ファンクションがあり RAW を入力として RAW を戻り値とするファンクションである。 このファンクションを SQL 文から呼び出すには DBMS_CRYPTO パッケージの定数を変換する必要がある。

使用例では 暗号化方式:AES256(Advanced Encryption Standard 鍵長 256 bit)、暗号ブロック連鎖: Cipher Block Chaining 、データ補完: PKCS #5 パディング: Password-Based Cryptography Standard を使用する。(用意されている暗号化の中で非常に強度の高い部類)
DBMS_CRYPTO で利用できる暗号化の種類と指定する定数名 (DBMS_CRYPTO.ENCRYPT_DES、DBMS_CRYPTO.ENCRYPT_AES256、 など)

SQL> select
  2     UTL_I18N.STRING_TO_RAW('123456789012345',  'AL32UTF8') "オリジナル",
  3     DBMS_CRYPTO.ENCRYPT(
  4       src => UTL_I18N.STRING_TO_RAW ('123456789012345',  'AL32UTF8'),
  5       /** typ => DBMS_CRYPTO.ENCRYPT_AES256 + DBMS_CRYPTO.CHAIN_CBC
  6                + DBMS_CRYPTO.PAD_PKCS5, **/
  7       typ => 8 + 256 + 4096,
  8       key => UTL_I18N.STRING_TO_RAW('PASSWORD**mypassword**PASSWORD**',  'AL32UTF8')
  9     ) "暗号化"
 10  from dual
 11  /
 
オリジナル                       暗号化
-------------------------------- --------------------------------
313233343536373839303132333435   7E646FBF9AD01BF3ED68E41CE13579CE

パッケージ仕様部に定義された定数を参照するには複数の方法があるが DBMS_OUTPUT を使用する。

SQL> execute dbms_output.put_line(DBMS_CRYPTO.ENCRYPT_AES256);
8
 
PL/SQLプロシージャが正常に完了しました。

SQL から直接利用する場合、暗号化する対象によっては、強度のある暗号化を使用しても SQL 文の中に暗号化に使用するパスフレーズが埋め込まれて暗号化されていないネットワーク上をそのまま流れることで暗号化する効果は低くなるので要注意。
例示しておきながら SQL で使用するためにパッケージの定数名を直接数値に書き換えてしまうのもあまりおススメできない。(将来、定数の数値を変更されたら違う暗号化になってしまったりする)

上記サンプルでの暗号化の鍵は 'PASSWORD**mypassword**PASSWORD**' のアスキーコード(7bit)を使用しているが x00 〜 xFF までのバイナリを使用した方が組み合わせでも辞書攻撃にでも有効なパスフレーズとなる。
システムで動的に生成するような場合には専用のファンクションが用意されている。⇒ DBMS_CRYPTO.RANDOMBYTES ファンクション

ORA-28234: キーの長さが短かすぎます。

鍵長は AES256 なので 256bit = 32byte の長さが必要。鍵長に過不足があると 「ORA-28234: キーの長さが短かすぎます。 」エラーが発生する。(キーのが長さが長すぎても同じエラーメッセージ)

SQL> select
  2     UTL_I18N.STRING_TO_RAW('123456789012345',  'AL32UTF8') "オリジナル",
  3     DBMS_CRYPTO.ENCRYPT(
  4       src => UTL_I18N.STRING_TO_RAW ('123456789012345',  'AL32UTF8'),
  5       /** typ => DBMS_CRYPTO.ENCRYPT_AES256 + DBMS_CRYPTO.CHAIN_CBC
  6                + DBMS_CRYPTO.PAD_PKCS5, **/
  7       typ => 8 + 256 + 4096,
  8       key => UTL_I18N.STRING_TO_RAW('SHORT-PASSWORD',  'AL32UTF8')
  9     ) "暗号化"   ----                ↑↑ 256bit になってない
 10  from dual
 11  /
   DBMS_CRYPTO.ENCRYPT(
   *
行3でエラーが発生しました。:
ORA-28234: キーの長さが短かすぎます。
ORA-06512: "SYS.DBMS_CRYPTO_FFI", 行3
ORA-06512: "SYS.DBMS_CRYPTO", 行13
ORA-06512: 行1

文字列を暗号化し PRINTABLE な文字列に変換するファンクション

入力文字列を AES256 で暗号化し Base64 化して戻すファンクション

-- 暗号化ファンクション
CREATE OR REPLACE FUNCTION TEXT_ENCRYPT(
  P_TEXT      VARCHAR2,
  P_PASSWORD  VARCHAR2
)
RETURN VARCHAR2
IS
  vEncrypted  RAW(2000);
BEGIN
  vEncrypted := DBMS_CRYPTO.ENCRYPT(
    src => UTL_I18N.STRING_TO_RAW (P_TEXT,  'AL32UTF8'),
    typ => DBMS_CRYPTO.ENCRYPT_AES256 + DBMS_CRYPTO.CHAIN_CBC
         + DBMS_CRYPTO.PAD_PKCS5,
    key => UTL_I18N.STRING_TO_RAW(RPAD(P_PASSWORD, 32, CHR(0)), 'AL32UTF8'));
  RETURN UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(vEncrypted));
END;
/
-- 復号化ファンクション
CREATE OR REPLACE FUNCTION TEXT_DECRYPT(
  P_ENCRYPTED  VARCHAR2,
  P_PASSWORD   VARCHAR2
)
RETURN VARCHAR2
IS
  vRaw  RAW(2000);
BEGIN
  vRaw := UTL_ENCODE.BASE64_DECODE(UTL_RAW.CAST_TO_RAW(P_ENCRYPTED));
  vRaw := DBMS_CRYPTO.DECRYPT(
    src => vRaw,
    typ => DBMS_CRYPTO.ENCRYPT_AES256 + DBMS_CRYPTO.CHAIN_CBC
         + DBMS_CRYPTO.PAD_PKCS5,
    key => UTL_I18N.STRING_TO_RAW(RPAD(P_PASSWORD, 32, CHR(0)), 'AL32UTF8'));
  RETURN UTL_I18N.RAW_TO_CHAR (vRaw, 'AL32UTF8');
END;
/
SQL> select
  2    text_encrypt('ないしょ話', 'mypass')
  3  from dual;
 
TEXT_ENCRYPT('ないしょ話','MYPASS')
--------------------------------------------------------------------------------
tfXPJwi79W10PP4WTC4f9w==
 
SQL> select
  2    text_decrypt('tfXPJwi79W10PP4WTC4f9w==', 'mypass')
  3  from dual;
 
TEXT_DECRYPT('TFXPJWI79W10PP4WTC4F9W==','MYPASS')
--------------------------------------------------------------------------------
ないしょ話


乱数、暗号化、ハッシュ関連事項

日本オラクル
■ 日本オラクル 株式会社
■ オラクルマスター資格 (オラクルマスターとは
■ Oracle のライセンスがわからない…
Oracle Direct (ネットで聞いても最後はここで要確認)