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

# 概要
PHPの拡張モジュールのphp-mcryptを使って暗号化、復号化をするサンプル。
インストールはこちら
[libmcrypt, php-mcrypt をCentOS 6.7にインストール]
(http://qiita.com/yotasasaki/items/b9a6242bbd03f31b184e)

# 実行
```
$ tree
.
├── app.php
├── mcrypt.php

$ php app.php
```
# サンプルコード

```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のラッパークラス

```php: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](http://php.net/manual/ja/function.mcrypt-module-open.php)**
暗号化のモジュールを、アルゴリズム、モードを指定してオープンします。
第一引数 algorithmは、[MCRYPT_暗号名](http://php.net/manual/ja/mcrypt.ciphers.php)が使えます。例えば、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](http://php.net/manual/ja/function.mcrypt-create-iv.php)**
暗号化のための値を生成します。
これが↑で行っている `$this->iv`つまりInitial Vectorです。
第一引数のsizeは、**[mcrypt_enc_get_iv_size](http://php.net/manual/ja/function.mcrypt-enc-get-iv-size.php)** で取得可能。
第二引数のsourceは、Linux環境なので [/dev/urandom](http://piyopiyocs.blog115.fc2.com/blog-entry-665.html) からランダムな値を取得することにしました。

**[mcrypt_generic_init](http://php.net/manual/ja/function.mcrypt-generic-init.php)**
**[mcrypt_generic](http://php.net/manual/ja/function.mcrypt-generic.php)**
**[mcrypt_generic_deinit](http://php.net/manual/ja/function.mcrypt-generic-deinit.php)**
**[mcrypt_module_close](http://php.net/manual/ja/function.mcrypt-module-close.php)**
この辺りは、mcryptの基本の流れになります。
他に、[mcrypt-encrypt](http://php.net/manual/ja/function.mcrypt-encrypt.php)、[mcrypt-decrypt](http://php.net/manual/ja/function.mcrypt-decrypt.php)など↑をラップしたメソッドもありますので、処理を細かく分ける必要が無ければ、こちらも利用可能かと。

# 参考
http://pentan.info/doc/block_cipher.html
[暗号利用モード wikipedia](https://ja.wikipedia.org/wiki/%E6%9A%97%E5%8F%B7%E5%88%A9%E7%94%A8%E3%83%A2%E3%83%BC%E3%83%89)