PHPのmcryptで暗号化、複号化するサンプル


概要

PHPの拡張モジュールのphp-mcryptを使って暗号化、復号化をするサンプル。
インストールはこちら
libmcrypt, php-mcrypt をCentOS 6.7にインストール

実行

$ tree
.
├── app.php
├── mcrypt.php

$ php app.php

サンプルコード

app.php
<?php
require_once "./mcrypt.php";

$text = "fizzbazz";
$mcrypt = new Mcrypt;

/*オリジナル*/
echo "Original Text: {$text} \r\n";
# Original Text: fizzbazz 

/*暗号化します*/
$encrypted = $mcrypt->encrypt($text); 
echo "Encrypted: {$encrypted} \r\n";
# Encrypted: KbR8BrizX2KfpMw5G6gxi0B6TLPhkRAShSY106kjO38= 

/*復号化します*/
$decrypted = $mcrypt->decrypt($encrypted);
echo "Decrypted: {$decrypted} \r\n";
# Decrypted: fizzbazz

php-mcryptのラッパークラス

mcrypt.php
<?php

class Mcrypt
{
    const SECRET = "5!47?92977d7fd5c1ALa6b07072c#";

    private $td;
    private $iv;
    private $key;

    private function initialize()
    {
        /* Open the cipher */
        $this->td = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_CBC, '');

        /* Create the IV and determine the keysize length*/
        if (!$this->iv) {
            $this->iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($this->td), MCRYPT_DEV_URANDOM);
        }
        $ks = mcrypt_enc_get_key_size($this->td);

         /* Create key */
        $this->key = substr(hash("sha256", self::SECRET), 0, $ks);
    }

    public function encrypt($input)
    {
        $this->initialize();

        /* Intialize encryption */
        mcrypt_generic_init($this->td, $this->key, $this->iv);

        /* Encrypt data */
        $encrypted = mcrypt_generic($this->td, base64_encode($input));

        $this->finalize();

        return base64_encode($encrypted);
    }

    public function decrypt($encrypted)
    {
        $this->initialize();

        /* Intialize encryption */
        mcrypt_generic_init($this->td, $this->key, $this->iv);

        $encrypted = base64_decode($encrypted, true);

        /* Decrypt encrypted string */
        $decrypted = mdecrypt_generic($this->td, $encrypted);

        $this->finalize();

        return base64_decode($decrypted, true);
    }

    private function finalize()
    {
        /* Terminate handle and close module */
        mcrypt_generic_deinit($this->td);
        mcrypt_module_close($this->td);
    }
}

説明

mcrypt_module_open
暗号化のモジュールを、アルゴリズム、モードを指定してオープンします。
第一引数 algorithmは、MCRYPT_暗号名が使えます。例えば、MCRYPT_RIJNDAEL_256は鍵とブロックの長さが256ビット。AESにも選定されたアルゴリズムなので、今回採用してみました。

第三引数のmodeは、MCRYPT_MODE_(ECBやCBC)となります。
ECBは初期化ベクトル($this->iv)を必要としない、比較的簡単な暗号化モードだそう。異なるサイト間のやり取り等で初期化ベクトルが共有できないケースや、そこまでセキュリティレベルを上げる必要が無い場合は、良いかも。ただし、一回パターンが見破られるとアウト。

CBCは初期化ベクトル($this->iv)がEncrypt,Decrypt時に同じものを指定する必要があります。毎回違うベクトルで暗号化するので、パターンが見破られる事はない。今回はCBCとしたので if (!$this->iv) として、暗号、複号とも同じ初期化ベクトルによって処理するようにしました。別クラスで処理する場合は、$this->ivの値も受渡して、Decryptする必要があります。

mcrypt_create_iv
暗号化のための値を生成します。
これが↑で行っている $this->ivつまりInitial Vectorです。
第一引数のsizeは、mcrypt_enc_get_iv_size で取得可能。
第二引数のsourceは、Linux環境なので /dev/urandom からランダムな値を取得することにしました。

mcrypt_generic_init
mcrypt_generic
mcrypt_generic_deinit
mcrypt_module_close
この辺りは、mcryptの基本の流れになります。
他に、mcrypt-encryptmcrypt-decryptなど↑をラップしたメソッドもありますので、処理を細かく分ける必要が無ければ、こちらも利用可能かと。

参考

http://pentan.info/doc/block_cipher.html
暗号利用モード wikipedia