Last active
November 10, 2022 07:51
-
-
Save comuttun/8347313 to your computer and use it in GitHub Desktop.
PHP Encrypt Sample with CodeBook.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* CodeBook.php | |
* @version 0.2.1 | |
* @see http://0-oo.net/sbox/php-tool-box/code-book | |
* @copyright 2009-2011 [email protected] | |
* @license http://0-oo.net/pryn/MIT_license.txt (The MIT license) | |
*/ | |
class CodeBook { | |
/** PKCS#5でパディング */ | |
const PAD_PKCS5 = 'PAD_PKCS5'; | |
/** Null文字でパディング */ | |
const PAD_NULL = "\0"; | |
/** スペースでパディング */ | |
const PAD_SPACE = ' '; | |
private $_cipher; | |
private $_mode; | |
private $_padding; | |
/** | |
* コンストラクタ | |
* デフォルトは、AES(ブロック長128bit)、CBCモード、PKCS#5でパディング | |
* @param string $cipher (省略可)暗号アルゴリズム | |
* @param string $mode (省略可)暗号モード | |
* @param string $padding (省略可)パディング方法(このクラスの定数 or 文字) | |
* @see http://www.php.net/manual/ja/mcrypt.ciphers.php | |
* @see http://www.php.net/manual/ja/mcrypt.constants.php | |
*/ | |
public function __construct($cipher = MCRYPT_RIJNDAEL_128, $mode = MCRYPT_MODE_CBC, $padding = self::PAD_PKCS5) { | |
$this->_cipher = $cipher; | |
$this->_mode = $mode; | |
$this->_padding = $padding; | |
} | |
/** | |
* 暗号化する | |
* 初期化ベクトル(IV)を渡さない場合、ランダムな初期化ベクトルを生成する | |
* @param string $key 暗号鍵 | |
* @param string $encryptee 暗号化するデータ | |
* @param string $iv (省略可)初期化ベクトル(ECBでは不要) | |
* @return array hex化した暗号化済みデータと、hex化した初期化ベクトル(IV) | |
*/ | |
public function encrypt($key, $encryptee, $iv = null) { | |
$this->_checkKeySize($key); | |
if (!$iv) { | |
$iv = $this->_getRandIv(); | |
} | |
if ($this->_padding === self::PAD_PKCS5) { | |
$encryptee = $this->padPkcs5($encryptee); | |
} else { | |
$encryptee = $this->pad($encryptee, $this->_padding); | |
} | |
$bin = mcrypt_encrypt($this->_cipher, $key, $encryptee, $this->_mode, $iv); | |
return array(bin2hex($bin), bin2hex($iv)); | |
} | |
/** | |
* 復号する | |
* @param string $key 暗号鍵 | |
* @param string $encrypted 暗号化されてhex化されたデータ | |
* @param string $iv (省略可)hex化した初期化ベクトル(ECBでは不要) | |
* @return string 復号したデータ | |
*/ | |
public function decrypt($key, $encrypted, $iv = null) { | |
$this->_checkKeySize($key); | |
$bin = $this->hex2bin($encrypted); | |
if ($iv) { | |
$iv = $this->hex2bin($iv); | |
} else { | |
$iv = $this->_getRandIv(); //Warningを出さないためのダミーのIV | |
} | |
$decrypted = mcrypt_decrypt($this->_cipher, $key, $bin, $this->_mode, $iv); | |
if ($this->_padding === self::PAD_PKCS5) { | |
$decrypted = $this->trimPkcs5($decrypted); | |
} else { | |
$decrypted = rtrim($decrypted, $this->_padding); | |
} | |
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化したデータをバイナリに変換する(bin2hex()の反対) | |
* @param string $hex hex化されたデータ | |
* @return string バイナリになったデータ | |
*/ | |
public function hex2bin($hex) { | |
return pack('H*', $hex); | |
} | |
/** | |
* 暗号鍵の長さをチェックする | |
* @param string $key 暗号鍵 | |
* @throws Exception 長さが不正な場合に例外を投げる | |
*/ | |
private function _checkKeySize($key) { | |
$sizes = mcrypt_module_get_supported_key_sizes($this->_cipher); | |
//可変の場合は空なのでチェックしない | |
if ($sizes && !in_array(strlen($key), $sizes)) { | |
throw new Exception("Invalid key length ($key)"); | |
} | |
} | |
/** | |
* ランダムな初期化ベクトル(IV)を生成する | |
* @return string 生成した初期化ベクトル | |
*/ | |
private function _getRandIv() { | |
srand(); | |
return mcrypt_create_iv($this->_getBlockSize(), MCRYPT_RAND); | |
} | |
/** | |
* 暗号アルゴリズムと暗号モードに応じたブロックサイズを取得する | |
* @return integer ブロックサイズ | |
*/ | |
private function _getBlockSize() { | |
return mcrypt_get_iv_size($this->_cipher, $this->_mode); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
require 'CodeBook.php'; | |
$key = '42a6c4a94d9fc42357f24362d1420f54'; | |
$codebook = new CodeBook(); | |
for ($i = 0; $i < 100; $i++) { | |
// AES(RIJNDAEL128), CBC, Padding with PKCS#5 | |
list($encrypted, $iv) = $codebook->encrypt($key, 'hogehoge'); | |
$iv_and_encrypted = "$iv##$encrypted"; | |
echo "iv_and_encrypted=$iv_and_encrypted\n"; | |
if (preg_match('/^(.+?)##(.+)$/', $iv_and_encrypted, $matches)) { | |
$matched_iv = $matches[1]; | |
$matched_encrypted = $matches[2]; | |
$decrypted = $codebook->decrypt($key, $matched_encrypted, $matched_iv); | |
echo "iv=$matched_iv, encrypted=$matched_encrypted, decrypted=$decrypted\n"; | |
} else { | |
echo "encrypted data format error"; | |
} | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment