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と全然関係ないような気がするのは気のせい?