すらいむがあらわれた

こまんど >  たたかう  にげる

PHPと.NETで3DESを使う場合の落とし穴

うまくいかなくてあれこれ検索していたらどうやら言語間で問題がある場合がありそうだったので、「php .NET 暗号」でぐぐって先人の立てた看板をみつけた。


PHPと.NETで暗号化の結果がマッチしない問題
http://d.hatena.ne.jp/red_snow/20101116/1289904165


私はもう穴に落ちた後だったけど、このおかげで無事這い上がれたのでもうここにもう1個看板を追加しておきます。

mcrypt_encrypt
http://www.php.net/manual/ja/function.mcrypt-encrypt.php
のページの下のコメント欄にPHPと.NETで3DESを使う場合の問題点と解決策が書いてあります。

jesse at pctest dot com 07-Dec-2004 10:43
http://www.php.net/manual/ja/function.mcrypt-encrypt.php#47973
ale_ferrer at yahoo dot com 24-Jul-2006 09:35
http://www.php.net/manual/ja/function.mcrypt-encrypt.php#68368


上記の下のほうのリンク先に載っているこの関数を使えば問題解決です。

// http://www.php.net/manual/ja/function.mcrypt-encrypt.php#68368 
// から引用
<?PHP
function encryptNET3DES($key, $vector, $text){
    $td = mcrypt_module_open (MCRYPT_3DES, '', MCRYPT_MODE_CBC, '');

    // Complete the key
    $key_add = 24-strlen($key);
    $key .= substr($key,0,$key_add);

    // Padding the text
    $text_add = strlen($text)%8;
    for($i=$text_add; $i<8; $i++){
        $text .= chr(8-$text_add);
    }

    mcrypt_generic_init ($td, $key, $vector);
    $encrypt64 = mcrypt_generic ($td, $text);
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);

     // Return the encrypt text in 64 bits code
    return $encrypt64;
}
?> 


リンク先で解説されている問題点をまとめます。


PHPmcryptモジュールの3DESでは192 bitのキーだけをうけつけるのですが, .NETやそのほかのツールの多くは128bitと192bit両方のキーを受け付けます。


・データパディングの仕方に違いがあります。
PHPmcryptモジュールは常にnull文字でデータパディングしますが、.NETは複数のパディングモードがあります。
http://msdn.microsoft.com/ja-jp/library/system.security.cryptography.paddingmode%28v=VS.100%29.aspx
(上記のリンクでは "Zeros" and "PKCS7" とありますが、.NET2.0以降で増えました。)
デフォルトは"PKCS7"のようです。
このためデータパディングの仕方を合わせる必要があります。