文書の過去の版を表示しています。
コメントと更新履歴は(準備中)へどうぞ。
PHPはphp-mcryptさえあればいろんな暗号アルゴリズムを使えるけど、いざやろうとすると意外に面倒。特に、Javaなど他のアプリやツールとやり取りするときとか。
IVやパディングについて考えるのは大したことではないと言えばそれまでだが、毎回チョコチョコ書くのはちょっと手間。パディングがPKCS#5の場合なんか特に。
なので手軽に暗号化と復号ができるクラスを作った。
クラス名はサイモン・シンの力作、暗号解読にちなんで。
この本によれば、PHPによる暗号化はCODEではなくCIPHERだそうだけれど。
MITライセンスで。
$key = '秘密の鍵'; $text = '秘密のメッセージ'; /* AES、CBC、Null文字でPAD */ $c1 = new CodeBook(); list($encrypted, $iv) = $c1->encrypt($key, $text); //暗号化 $decrypted = $c1->decrypt($key, $encrypted, $iv); //復号 echo $text . ' => ' . $decrypted; // => "秘密のメッセージ => 秘密のメッセージ" echo '<br />'; echo var_dump($text === $decrypted); // => bool(true) echo '<hr />'; /* Blowfish、CBC、PKCS#5でPAD */ $c2 = new CodeBook(MCRYPT_BLOWFISH); $padded = $c2->padPkcs5($text); //パディング list($encrypted, $iv) = $c2->encrypt($key, $padded); //暗号化 $decryptedAndPadded = $c2->decrypt($key, $encrypted, $iv); //復号 $decrypted = $c2->trimPkcs5($decryptedAndPadded); //PADを除去 echo $text . ' => ' . $decrypted; // => "秘密のメッセージ => 秘密のメッセージ" echo '<br />'; echo var_dump($text === $decrypted); // => bool(true) echo '<hr />'; /* RIJNDAEL256、ECB、スペースでPAD */ $c3 = new CodeBook(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); $padded = $c3->pad($text, ' '); //パディング list($encrypted) = $c3->encrypt($key, $padded); //暗号化 $decrypted = $c3->decrypt($key, $encrypted, null, ' '); //復号&PADを除去 echo $text . ' => ' . $decrypted; // => "秘密のメッセージ => 秘密のメッセージ" echo '<br />'; echo var_dump($text === $decrypted); // => bool(true)
<?php /** * CodeBook.php * @version 0.1.0 * @see http://0-oo.net/sbox/php-tool-box/code-book * @copyright 2009 dgbadmin@gmail.com * @license http://0-oo.net/pryn/MIT_license.txt (The MIT license) */ <?php class CodeBook { private $_cipher; private $_mode; /** * コンストラクタ * デフォルトは、AES(ブロック長128bits)/CBCモード * @param string $cipher (省略可)暗号アルゴリズム * @param string $mode (省略可)暗号モード * @see http://jp2.php.net/manual/ja/mcrypt.ciphers.php * @see http://jp2.php.net/manual/ja/mcrypt.constants.php */ public function __construct($cipher = MCRYPT_RIJNDAEL_128, $mode = MCRYPT_MODE_CBC) { $this->_cipher = $cipher; $this->_mode = $mode; } /** * 暗号化する * IVを渡さない場合、ランダムなIVが生成される * @param string $key 暗号鍵 * @param string $encryptee 暗号化するデータ * @param string $iv (省略可)初期化ベクトル * @return array hex化した暗号化済みデータと、hex化したIV */ public function encrypt($key, $encryptee, $iv = null) { if (!$iv) { $iv = $this->_getRandIV(); } $bin = mcrypt_encrypt($this->_cipher, $key, $encryptee, $this->_mode, $iv); return array(bin2hex($bin), bin2hex($iv)); } /** * 復号する * mcrypt_encrypt()のデフォルトのパディング文字は"\0"(Null文字) * @param string $key 復号鍵 * @param string $encrypted 暗号化されたデータ * @param string $iv (省略可)hex化した初期化ベクトル(ECBでは不要) * @param string $trimChar (省略可)除去するパディング文字 * @return string 復号したデータ */ public function decrypt($key, $encrypted, $iv = null, $trimChar = "\0") { $bin = self::hex2bin($encrypted); if ($iv) { $iv = self::hex2bin($iv); } else { $iv = $this->_getRandIV(); //Warningを出さないためのダミーのIV } $decrypted = mcrypt_decrypt($this->_cipher, $key, $bin, $this->_mode, $iv); if ($trimChar !== false) { $decrypted = rtrim($decrypted, $trimChar); } return $decrypted; } /** * ブロック長に合わせてパディングする * @param string $data パディング対象のデータ * @param string $padChar パディング文字 * @return string パディングしたデータ */ public function pad($data, $padChar) { $size = $this->_getBlockSize(); return str_pad($data, ceil(strlen($data) / $size) * $size, $padChar); } /** * PKCS#5でパディングする * @param string $data パディング対象のデータ * @return string パディングしたデータ */ public function padPkcs5($data) { $size = $this->_getBlockSize(); $padLen = $size - (strlen($data) % $size); return $data . str_repeat(chr($padLen), $padLen); } /** * PKCS#5のパディングを除去する * @param string $data PKCS#5でパディングされたデータ * @return string パディングしたデータ */ public function trimPkcs5($data) { return substr($data, 0, ord(substr($data, -1, 1)) * -1); } /** * hex化したデータをバイナリに変換する * @param string $hex hex化されたデータ * @return string バイナリになったデータ */ public static function hex2bin($hex) { return pack('H*', $hex); } private function _getRandIV() { srand(); return mcrypt_create_iv($this->_getBlockSize(), MCRYPT_RAND); } private function _getBlockSize() { return mcrypt_get_iv_size($this->_cipher, $this->_mode); } }