暗号化・複合化を行う ブロック暗号

PHPでブロック暗号を行うにはMcrypt関数で可能です。
AESやDES、Blowfishなどが使用可能です。

[参考記事] ブロック暗号とは
[参考記事] Javaで暗号化・複合化を行う ブロック暗号
[参考記事] Perlで暗号化・複合化を行う ブロック暗号
[参考記事] Rubyで暗号化・複合化を行う ブロック暗号

PHPではCrypt_BlowfishというPEARもあります。
[参考記事] テキストを可逆的な暗号化する Crypt_Blowfish

サンプルコード
使用できる暗号利用モードの一覧
使用できる暗号アルゴリズムの一覧

Mcrypt関数を使用するにはPHPにmcryptが組み込まれている必要があり、mcryptはlibmcryptを必要とします。
PHP5以降では、libmcrypt2.5.6以降が必要です。
Linuxなどではyumでphp-mcryptパッケージがこれに該当し、yumでのインストールは次のようにします。

yum -y install php-mcrypt

Windowsの場合はPHP 5.2以降でライブラリに組み込まれています。

この暗号化方式はアルゴリズム規定のブロック長に分割して秘密鍵を用いて暗号化を行います。
規定のブロック長に分割する方式を暗号利用モードブロック長に満たないときの補完方法をパディング方式といいます。
暗号利用モードで分割するときに前の平文ブロックの結果を次の平文に使用しますが、この最初のブロックで使用される値がIV(初期化ベクトル)です。

まとめ
暗号化の流れ
(1) ブロック長に満たない部分をパディング方式で補完する。
(2) アルゴリズムに対応したブロック長に分割する。
 このときの分割ルールを決めるのが暗号利用モード
 分割モードによっては初期値が必要で、これがIV(初期化ベクトル)
(3) 暗号鍵を用いてアルゴリズムで暗号化する。
(4) 分割されたデータを結合する。

復号化の流れ
(1) アルゴリズムに対応したブロック長に分割する。
(2) 暗号鍵を用いてアルゴリズムで復号化する。
(3) 暗号利用モードを元に分割されたデータを結合する。
 分割モードによっては初期値が必要で、これがIV(初期化ベクトル)
(4) 補完されたパディングをパディング方式で除去する。

ブロック暗号では、
ブロック長
秘密鍵
暗号アルゴリズム
暗号利用モード
パディング方式
IV(初期化ベクトル)
の6つのキーワードが重要です。

使用できる暗号化アルゴリズムは組み込まれているlibmcryptに依存します。
ブロック長、共通鍵の長さは使用する暗号アルゴリズムに依存します。

暗号利用モードにはECB、CBD、OFB、CFBなどが使用できます。

パディング方式はZeroBytePaddingのみです。
パディング不要な状態であればZeroBytePaddingは何もしないので、PKCS#5 Paddingなどは独自に実装することで使用できます。
NoPaddingはできません。
ZeroBytePaddingではブロック長に満たない長さをNULL(0x00)で埋める方式ですが、末尾の0x00が本来生成された値の末尾なのかパディングされた値なのかを判断できないため、使用しないほうがいいです。

スポンサーリンク

サンプルコード

PKCS#5 Paddingでのサンプルです。

// 暗号化を行う
function cipher_encrypt($input,$key)
{
  // 指定した暗号のブロックサイズを得る
  $size = mcrypt_get_block_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
  // PKCS5Padding ブロック長に満たないサイズを埋める
  $input = pkcs5_pad($input, $size);
  // 使用するアルゴリズムおよびモードのモジュールをオープンする
  $td = mcrypt_module_open(MCRYPT_BLOWFISH, '',  MCRYPT_MODE_ECB, '');
  // オープンされたアルゴリズムの IV の大きさを返す
  $ivsize = mcrypt_enc_get_iv_size($td);
  // MCRYPT_RAND の初期化を行う
  srand();
  // 乱数ソースから初期化ベクトル(IV)を生成する
  // ECB以外では復号にこのIV(初期化ベクトル)が必要です。
  // ECBではIVは使用されませんが、IVがないとエラーが出ます。
  $iv = mcrypt_create_iv($ivsize, MCRYPT_RAND);
  // 暗号化に必要な全てのバッファを初期化する
  mcrypt_generic_init($td, $key, $iv);
  // データを暗号化する
  $data = mcrypt_generic($td, $input);
  // 暗号化モジュールを終了する
  mcrypt_generic_deinit($td);
  // mcrypt モジュールを閉じる
  mcrypt_module_close($td);
  return $data;
}

// 複合化を行う
function cipher_decrypt($input,$key)
{
  // 指定した暗号のブロックサイズを得る
  $size = mcrypt_get_block_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
  // 使用するアルゴリズムおよびモードのモジュールをオープンする
  $td = mcrypt_module_open(MCRYPT_BLOWFISH, '',  MCRYPT_MODE_ECB, '');
  // オープンされたアルゴリズムの IV の大きさを返す
  $ivsize = mcrypt_enc_get_iv_size($td);
  // MCRYPT_RAND の初期化を行う
  srand();
  // 乱数ソースから初期化ベクトル(IV)を生成する
  // ECB以外では暗号化に用いたIV(初期化ベクトル)が必要です。
  // ECBではIVは使用されませんが、IVがないとエラーが出ます。
  $iv = mcrypt_create_iv($ivsize, MCRYPT_RAND);
  // 暗号化に必要な全てのバッファを初期化する
  mcrypt_generic_init($td, $key, $iv);
  // データを復号する
  $data = mdecrypt_generic($td, $input);
  // 暗号化モジュールを終了する
  mcrypt_generic_deinit($td);
  // mcrypt モジュールを閉じる
  mcrypt_module_close($td);
  // PKCS5Padding 埋められたバイト値を除く
  $data = pkcs5_unpad($data, $size);
  return $data;
}

// PKCS5Padding
// ブロック長に満たないサイズを埋める
function pkcs5_pad($text, $blocksize)
{
  $pad = $blocksize - (strlen($text) % $blocksize);
  return $text . str_repeat(chr($pad), $pad);
}

// PKCS5Padding
// 埋められたバイト値を除く
function pkcs5_unpad($text)
{
  $pad = ord($text{strlen($text)-1});
  if ($pad > strlen($text)) return false;
  if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false;
  return substr($text, 0, -1 * $pad);
}

/******************
暗号化例
******************/
// 暗号化するデータ
$data = "この文字を暗号化します。";
// 暗号キー
$key = "ABCDEF";

echo "元のデータ : " . $data;
echo "<br />";
$encrypt = cipher_encrypt($data,$key);
echo "暗号化されたデータ : " . $encrypt;
echo "<br />";
$decrypt = cipher_decrypt($encrypt,$key);
echo "複合化されたデータ : " . $decrypt;

使用できる暗号利用モードの一覧

MCRYPT_MODE_ECBelectronic codebook他のキーを暗号化するといったランダムデータに適しています。出力データが短くランダムであるというECBの短所は、都合の良い逆の効果を持っています。
MCRYPT_MODE_CBCcipher block chaining特に、ECB よりも著しく高いセキュリティでファイルを暗号化する用途に適しています。
MCRYPT_MODE_CFBcipher feedback1 バイト毎に暗号化する必要があるバイトストリームを暗号化する際に最も適したモードです。
MCRYPT_MODE_OFBoutput feedback、8 ビット形式CFBと互換性が ありますが、エラーの伝播が許容されないアプリケーションに使用することが可能です。このモードは(8 ビットモードで処理を行うため)安全ではなく、使用は推奨されません。
MCRYPT_MODE_NOFBoutput feedback、nビット形式OFBと互換ですが、アルゴリズムのブロックサイズを変更可能なため、より安全です。
MCRYPT_MODE_STREAM"WAKE" や "RC4" のようないくつかのストリームアルゴリズムを読み込む追加のモードです。

使用できる暗号アルゴリズムの一覧

MCRYPT_3DES
MCRYPT_ARCFOUR_IV (libmcrypt > 2.4.x のみ)
MCRYPT_ARCFOUR (libmcrypt > 2.4.x のみ)
MCRYPT_BLOWFISH
MCRYPT_CAST_128
MCRYPT_CAST_256
MCRYPT_CRYPT
MCRYPT_DES
MCRYPT_DES_COMPAT (libmcrypt 2.2.x のみ)
MCRYPT_ENIGMA (libmcrypt > 2.4.x のみ、MCRYPT_CRYPT へのエイリアス)
MCRYPT_GOST
MCRYPT_IDEA (非フリー)
MCRYPT_LOKI97 (libmcrypt > 2.4.x のみ)
MCRYPT_MARS (libmcrypt > 2.4.x のみ、非フリー)
MCRYPT_PANAMA (libmcrypt > 2.4.x のみ)
MCRYPT_RIJNDAEL_128 (libmcrypt > 2.4.x のみ)
MCRYPT_RIJNDAEL_192 (libmcrypt > 2.4.x のみ)
MCRYPT_RIJNDAEL_256 (libmcrypt > 2.4.x のみ)
MCRYPT_RC2
MCRYPT_RC4 (libmcrypt 2.2.x のみ)
MCRYPT_RC6 (libmcrypt > 2.4.x のみ)
MCRYPT_RC6_128 (libmcrypt 2.2.x のみ)
MCRYPT_RC6_192 (libmcrypt 2.2.x のみ)
MCRYPT_RC6_256 (libmcrypt 2.2.x のみ)
MCRYPT_SAFER64
MCRYPT_SAFER128
MCRYPT_SAFERPLUS (libmcrypt > 2.4.x のみ)
MCRYPT_SERPENT(libmcrypt > 2.4.x のみ)
MCRYPT_SERPENT_128 (libmcrypt 2.2.x のみ)
MCRYPT_SERPENT_192 (libmcrypt 2.2.x のみ)
MCRYPT_SERPENT_256 (libmcrypt 2.2.x のみ)
MCRYPT_SKIPJACK (libmcrypt > 2.4.x のみ)
MCRYPT_TEAN (libmcrypt 2.2.x のみ)
MCRYPT_THREEWAY
MCRYPT_TRIPLEDES (libmcrypt > 2.4.x のみ)
MCRYPT_TWOFISH (古い mcrypt 2.x 系か、あるいは mcrypt > 2.4.x )
MCRYPT_TWOFISH128 (TWOFISHxxx は 2.x の新しいバージョンで使用可能ですが、2.4.x では使用できません)
MCRYPT_TWOFISH192
MCRYPT_TWOFISH256
MCRYPT_WAKE (libmcrypt > 2.4.x のみ)
MCRYPT_XTEA (libmcrypt > 2.4.x のみ)

関連記事

スポンサーリンク

Google Chromeで一部の文字だけ四角記号に文字化けするときの対処法

ホームページ製作・web系アプリ系の製作案件募集中です。

上に戻る