Do You PHP はてブロ

Do You PHPはてなからはてブロに移動しました

Oracle 9.2のDBMS_OBFUSCATION_TOOLKITを使って3DES

元ネタは以下のURLにある「Oracle 10g XEのDBMS_CRYPTOを使ってAES」です。

調べてみるとDBMS_CRYPTOがDBMS_OBFUSCATION_TOOLKITの後継っぽいので、「ひょっとしてできるかなぁ」と思い、ストアドパッケージを作ってみました。まあ、ほとんどDBMS_OBFUSCATION_TOOLKITの単なるwrapperですが。。。

CREATE OR REPLACE PACKAGE des
/**
 * @author SHIMOOKA Hideyuki <shimooka@doyouphp.jp>
 */
IS
FUNCTION encrypt(data IN VARCHAR2, key IN VARCHAR2) RETURN VARCHAR2;
FUNCTION decrypt(data IN VARCHAR2, key IN VARCHAR2) RETURN VARCHAR2;
END;
/

CREATE OR REPLACE PACKAGE BODY des
/**
 * @author SHIMOOKA Hideyuki <shimooka@doyouphp.jp>
 * @see ftp://ftp.ashisuto.co.jp/pub/standard/vol81/obfuscation_toolkit.pdf
 */
IS
FUNCTION encrypt(
    data IN VARCHAR2,
    key IN VARCHAR2
)
RETURN VARCHAR2
IS
    encrypted_string VARCHAR2(2048);
    data_string VARCHAR2(2048) := data;
BEGIN
    FOR i IN 1..(8 - MOD(LENGTHB(data), 8)) LOOP
        data_string := data_string || ' ';
    END LOOP;
    DBMS_OBFUSCATION_TOOLKIT.DES3Encrypt(
        input_string => data_string,
        key_string => key,
        encrypted_string => encrypted_string);
    RETURN RAWTOHEX(UTL_RAW.CAST_TO_RAW(encrypted_string));
EXCEPTION
    WHEN OTHERS THEN
        RETURN SQLCODE;
END;

FUNCTION decrypt(
    data IN VARCHAR2,
    key IN VARCHAR2
)
RETURN VARCHAR2
IS
    decrypted_string VARCHAR2(2048);
BEGIN
    DBMS_OBFUSCATION_TOOLKIT.DES3Decrypt(
        input_string => UTL_RAW.CAST_TO_VARCHAR2(HEXTORAW(data)),
        key_string => key,
        decrypted_string => decrypted_string);
    RETURN RTRIM(decrypted_string);
EXCEPTION
    WHEN OTHERS THEN
        RETURN SQLCODE;
END;

END des;
/

des.encryptで暗号化、des.decryptで復号化です。引数は

  • des.encrypt:暗号化する文字列、暗号キー
  • des.decrypt:暗号化された文字列、暗号キー

です。
当然ですが、同じ暗号キーを使わないと復号化できません。また、鍵の管理は別途考慮する必要があります。
DBMS_OBFUSCATION_TOOLKITがサポートしている3DESはCBCモードの2キー/3キーですが、このパッケージでは2キーです。このため、暗号キーには128ビット(16バイト)のキーを指定してください。
もう一つ。des.encryptのコードの最初で、暗号化する文字列に半角スペースを追加していますが、使っているDBMS_OBFUSCATION_TOOLKIT.DESEncryptの制限で、暗号化する文字列が8バイトの倍数でないとエラー(ORA-28231)になるため、強制的に付けています。このため、des.deccryptの最後で強制的にRTRIMしていますので、最後にスペースが付いた文字列の復号化は完全でない場合があります。
個人的には「SHA1などのハッシュ値だけで済む場合はハッシュだけで済ませたい」と思うんですが、どうしても機密情報をDBに保存しなければならないとか、顧客から安易に「データを暗号化してくれ」みたいな要望が出てくることもありますので、そういった場面で使えるのかな、と思います。まあ、安易に「暗号化」を考えるのもどうなんでしょうねぇ。。。あ。利用は自己責任でお願いしますね ;-)
それにしても、Oracleのサイトの記事PHPと全然関係ないような気がするのは気のせい?