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; } ?>
リンク先で解説されている問題点をまとめます。
・PHPのmcryptモジュールの3DESでは192 bitのキーだけをうけつけるのですが, .NETやそのほかのツールの多くは128bitと192bit両方のキーを受け付けます。
・データパディングの仕方に違いがあります。
PHPのmcryptモジュールは常にnull文字でデータパディングしますが、.NETは複数のパディングモードがあります。
http://msdn.microsoft.com/ja-jp/library/system.security.cryptography.paddingmode%28v=VS.100%29.aspx
(上記のリンクでは "Zeros" and "PKCS7" とありますが、.NET2.0以降で増えました。)
デフォルトは"PKCS7"のようです。
このためデータパディングの仕方を合わせる必要があります。