PHP暗号化ガイドはじめに理想的な世の中では、「暗号化」や「セキュリティ」といった言葉は存在すらしないでしょう。しかし現実の世界は完全とはほど遠いものです。ですから、ソフトウェア開発者はアプリケーションのセキュリティ対策に相応の時間をかけなければなりません。暗号化はSSL/TLS、証明書、デジタル署名などと同様、セキュリティというパズルの1ピースにすぎません。この記事では、PHPを使って最も一般的な暗号化アルゴリズムを実装する方法を説明します。PHPデフォルトの暗号化機能に加えて、多様な暗号化ライブラリやパッケージの使用法を幅広く紹介していきます。この記事のサンプルコードでは、textfile.txtという小さなテキストファイルを使用します。このファイルには次のようなプレーンテキストが含まれています。 For every difficult and complicated question there is an answer that is simple, easily understood, and wrong. H.L. Mencken PHPデフォルトの暗号化関数PHPには3つの暗号化関数、md5()、crypt()、sha1()が用意されています。md5()関数のプロトタイプは次のとおりです。string md5(string $str [, bool $raw_output ]) $str引数は、暗号化される文字列を表します。$raw_output引数にFALSE(デフォルト)を渡すと、関数は32文字の16進数を返します。TRUEを渡すと、16バイトのバイナリ値そのものを返します。PHPの crypt()関数は、一方向の暗号化を行う関数です。この関数を使用すると、入力したパスワードが、保存されている暗号化済みパスワードと一致するかどうかを簡単に確認できます(暗号化済みパスワードを復号する手間が省けます)。crypt()関数のプロトタイプは次のとおりです。string crypt (string $str [, string $salt ]) $str引数は、暗号化される文字列です。オプションの$salt引数は、暗号化のベースとなる文字列(ソルト)です。ソルト文字列を指定しない場合、PHPは関数呼び出しごとにランダムにソルト文字列を生成します。PHPの sha1()関数は、文字列のSHA-1ハッシュを計算します。sha1()関数のプロトタイプは次のとおりです。string sha1 (string $str [, bool $raw_output ]) $str引数は入力文字列を表します。オプションの$raw_output引数にTRUEを設定すると、関数はバイナリ形式そのままのSHA-1ハッシュを20文字分の長さで返します。FALSEを設定すると、16進数表記で40文字分を返します。実際の例を見てみましょう。以下のコードは、PHPデフォルトの暗号化関数を使ってtextfile.txtの内容を暗号化し、その結果をencrypted.txtファイル(図1を参照)に出力する方法を示しています。 図1 暗号化されたファイル。exrypted.txtファイルには、PHPデフォルト関数のmd5、crypt、sha1で暗号化したパスワードが入っています。 ![]()
<?php
$file = 'textfile.txt';
$initial_contents = file_get_contents($file);
if($initial_contents){
$password = 'OctaviaAnghel';
//Calculates the md5 hash
$md5_data = md5($password);
//This function encrypts data
$crypt = crypt($password);
//Calculate the sha1 hash
$sha1 = sha1($password);
$encrypted_file = @fopen('encrypted.txt','w');
$ok_encrypt
= @fwrite($encrypted_file,'md5: '. $md5_data."\r¥".'crypt:
'.$crypt."\r¥".'sha1: '.$sha1);
if($ok_encrypt){
echo 'The encrypted code was succesfully created'.
' in encrypted_file.txt!!!'.'
';
}
else{
echo ("The write of this file failed!");
}
@fclose($encrypted_file);
}
?>
表1 PHPでの暗号化と復号に使われるパッケージおよびライブラリ
MCryptを用いた大規模データの暗号化MCryptを使用すると、開発者はさまざまな暗号化関数を用いてファイルやデータストリームを暗号化できます。暗号に関する専門知識は必要ありません。MCryptは、Blowfish、DES、TripleDES、SAFER-SK128、TWOFISH、TEA、RC2、3-WAY、SAFER-SK64などのブロックアルゴリズムと、いくつかの「利用モード」(modes of operation)に幅広く対応しています。通常、MCryptなどのブロック暗号は、多くは64または128ビットの固定長データブロックを取り扱います。しかし、メッセージはどんな長さにもなりうることと、同じプレーンテキストを同じ鍵で暗号化すると常に同じ結果となることから、任意長のメッセージにもブロック暗号を適用できるようにする解決策がいくつか考え出されてきました。こうした解決策は、ブロック暗号の利用モードとして知られています。MCryptがサポートするモードには、CBC、CFB、CTR、ECB、OFB、NCFBがあります。MCryptの付随ライブラリにLibmcryptというものがあり、実際の暗号化関数はこちらのライブラリに含まれています。Windowsユーザーはこちらで、Linuxユーザーはこちらでそれぞれダウンロードできます。 著者注
PHP 5.0.0を使用している場合は、libmcrypt Version 2.5.6以上も必要となります。
Libmcryptのインストール手順は次のとおりです。
著者注
Linuxの場合は、libmcrypt-x.x.tar.gzファイルをダウンロードし、同梱されているインストール指示に従ってください。
MCryptでは、CBC、OFB、CFB、ECBの4つの暗号モードを使用できます。libmcrypt-2.4.x以上を使用しているのであれば、MCrypt関数はnOFBおよびSTREAM暗号モードでも動作します。表2に、一般的に利用される暗号モードと、それぞれいつ使用するかを簡単に示します。表2 MCryptのよく使用される暗号モード
著者注
サポートされる暗号は変更される場合があるため、現在サポートされている暗号を定期的にチェックしてください。
MCryptの例それでは、MCryptを使用してテキストファイルの内容を暗号化および復号化する方法を実際の例で見ていきましょう。先ほどの例と同じように、textfile.txtの内容を暗号化し、その結果をencrypted.txtファイルに格納します。ただし今回の例では、さらに続けてencrypted.txtファイルを復号し、暗号解除されたテキストをnewfile.txtファイルに格納します。// Listing file_encrypt.php <?php $file = 'textfile.txt'; $initial_contents = file_get_contents($file); if($initial_contents){ //This function opens the module of the algorithm and //the mode to be used $td = mcrypt_module_open('tripledes', '', 'ecb', ''); //Create an initialization vector (IV) from a random source $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND); //This function initializes all buffers needed for encryption mcrypt_generic_init($td, $initial_contents, $iv); //This function encrypts data $encrypted_data = mcrypt_generic($td, $initial_contents); $encrypted_file = @fopen('encrypted.txt','w'); $ok_encrypt = @fwrite($encrypted_file,$encrypted_data); if($ok_encrypt){ echo 'The encrypted code was succesfully created '. 'in encrypted_file.txt!!!'.'<br />'; } else{ echo ("The write of this file failed!"); } @fclose($encrypted_file); mcrypt_generic_init($td, $initial_contents, $iv); //This function decrypts data $p_t = mdecrypt_generic($td, $encrypted_data); $newfile = @fopen('newfile.txt','w'); $ok_decrypt = @fwrite($newfile,$p_t); if($ok_decrypt){ echo 'The decrypted code was succesfully created '. 'in newfile.txt!!!'.'<br />'; } else{ echo ("The write of this file failed!"); } @fclose($newfile); //This function deinitializes an encryption module mcrypt_generic_deinit($td); //Close the mcrypt module mcrypt_module_close($td); } ?> MHashによるハッシュの作成MHashは無料のライブラリで、開発者は数多くのハッシュアルゴリズムから使用するものを選べます。これらのアルゴリズムを使用して、チェックサムの計算、メッセージダイジェストの作成、他の署名の作成を行うことができます。Libmhashのインストール
サポート対象ハッシュMHashが現在サポートするハッシュは次のとおりです。
<?php $file = 'textfile.txt'; $initial_contents = file_get_contents($file); if($initial_contents){ //mhash() applies a hash function specified by MHASH_MD5 //to the $initial_contents $encrypted = mhash(MHASH_MD5, $initial_contents); // get current Unix timestamp $current = time(); $salt = $current; $password = "Octavia"; //mhash_keygen_s2k generates a key according to the hash function //given and the password provided by the user. $hash = mhash_keygen_s2k(MHASH_GOST, $password, $salt, 20); //concatenate the $salt with the $hash $key = $salt . "|" . bin2hex($hash); $encrypted_file = @fopen('encrypted.txt','w'); $ok_encrypt = @fwrite($encrypted_file, 'mhash: '.bin2hex($encrypted).' mhash_keygen_s2k: '.$key); if($ok_encrypt){ echo 'The encrypted code was succesfully created '. 'in encrypted_file.txt !!!'.'<br />'; } else{ echo ("The write of this file failed!"); } @fclose($encrypted_file); } ?> 秘密鍵とCrypt_Blowfish秘密鍵暗号方式では、1つの鍵を暗号化と復号の両方に使用します。このため「対称鍵」とも呼ばれます。例えば、一般的に使われるDESアルゴリズムは秘密鍵アルゴリズムです。Crypt_Blowfish PEARパッケージは、Blowfishブロック暗号に基づいており、秘密鍵あり/なしの双方向の暗号化に対応しています。Crypt_BlowfishパッケージはMCryptを必要としませんが、インストールされていれば使用できます。最新のリリースバージョンは1.0.1(安定版)です。インストール方法は、他のPEARパッケージと同様です。> pear install pear_package_name require_once 'Crypt/Blowfish.php'; <?php require_once 'Crypt/Blowfish.php'; $file = 'textfile.txt'; $initial_contents = file_get_contents($file); if($initial_contents){ $bf = new Crypt_Blowfish('some secret key!'); // Encrypts a string $encrypted = $bf->encrypt($initial_contents); $encrypted_file = @fopen('encrypted.txt','w'); $ok_encrypt = @fwrite($encrypted_file,$encrypted); if($ok_encrypt){ echo 'The encrypted code was succesfully created '. 'in encrypted_file.txt!!!'.'<br />'; } else{ echo ("The write of this file failed!"); } @fclose($encrypted_file); // Decrypts an encrypted string $plaintext = $bf->decrypt($encrypted); $newfile = @fopen('newfile.txt','w'); $ok_decrypt = @fwrite($newfile,$plaintext); if($ok_decrypt){ echo 'The decrypted code was succesfully created '. 'in newfile.txt!!!'.'<br />'; } else{ echo ("The write of this file failed!"); } @fclose($newfile); } ?> Crypt_RSAパッケージによる任意長の鍵を用いた暗号化Crypt_RSAパッケージは双方向の暗号化をサポートし、RSAブロック暗号を基盤としています。Crypt_RSAでは任意長の鍵を使った暗号化と復号を行うことができます。最新バージョンは1.0.0(安定版)です。インストール方法は、他のPEARパッケージと同様です。> pear install pear_package_name
<?php require_once 'Crypt/RSA.php'; //Generates the pair keys function generate_key_pair() { global $public_key,$private_key; $key_pair = new Crypt_RSA_KeyPair(32); //Returns public key from the pair $public_key = $key_pair->getPublicKey(); //Returns private key from the pair $private_key = $key_pair->getPrivateKey(); } //Check runtime errors function check_error(&$obj) { if ($obj->isError()){ $error = $obj->getLastError(); switch ($error->getCode()) { case CRYPT_RSA_ERROR_WRONG_TAIL : // nothing to do break; default: // echo error message and exit echo 'error: ', $error->getMessage(); exit; } } } $file = 'textfile.txt'; generate_key_pair(); $plain_text = file_get_contents($file); //get string represenation of the public key $key = Crypt_RSA_Key::fromString($public_key->toString()); $rsa_obj = new Crypt_RSA; check_error($rsa_obj); //Ecnrypts $plain_text by the key $key. $encrypted = $rsa_obj->encrypt($plain_text, $key); $encrypted_file = @fopen('encrypted.txt','w'); $ok_encrypt = fwrite($encrypted_file,$encrypted); if($ok_encrypt){ echo 'The encrypted code was succesfully created '. 'in encrypted_file.txt!!!'.'<br />'; } else{ echo ("The write of this file failed!"); } @fclose($encrypted_file); $enc_text = $encrypted; //Get string represenation of the private key $key2 = Crypt_RSA_Key::fromString($private_key->toString()); check_error($key2); //Check encrypting/decrypting function's behaviour $rsa_obj->setParams(array('dec_key' => $key2)); check_error($rsa_obj); //Decrypts $enc_text $decrypted = $rsa_obj->decrypt($enc_text); $newfile = @fopen('newfile.txt','w'); $ok_decrypt = @fwrite($newfile,$decrypted); if($ok_decrypt){ echo 'The decrypted code was succesfully created '. 'in newfile.txt!!!'.'<br />'; } else{ echo ("The write of this file failed!"); } @fclose($newfile); ?> Crypt_HMACでのハッシュ生成Crypt_HMAC PEARパッケージには、RFC 2104準拠のハッシュの算出に使用できるクラスが含まれています。Crypt_HMACの使い方は簡単で、秘密鍵と使用したいハッシュメソッド、そしてプレーンテキストの文字列を与えるだけです。Crypt_HMACではMD5とSHA-1アルゴリズムの両方をサポートしています。最新バージョンの安定版リリースは1.0.0です。インストール方法は他のPEARパッケージと同様です。> pear install pear_package_name
<?php
require_once 'Crypt/HMAC.php';
//Creating a key by repeating the "0x0b" character for 20 times
$key = str_repeat(chr(0x0b), 20);
//Creating an instance of the Crypt_HMAC class
//$crypt = new Crypt_HMAC($key, 'md5');
$crypt = new Crypt_HMAC($key, 'md5');
//Hashing function
echo $crypt->hash('Hello')."<br />";
$key = str_repeat(chr(0xaa), 10);
$data = str_repeat(chr(0xdd), 50);
//Sets key to use with hash
$crypt->setKey($key);
echo $crypt->hash($data)."¥";
?>
Crypt_DiffieHellmanパッケージでの秘密鍵の生成このPEARパッケージは、Diffie-Hellman鍵交換暗号化プロトコルをPHP5用に実装したものです。このプロトコルを使用して外部の二者のために秘密鍵を生成すると、両者は生成された鍵を使って、安全性の低い経路であっても通信を行えるようになります。最新リリースはバージョン0.2.1(ベータ版)で、他のPEARパッケージと同じ方法でインストールできます。> pear install pear_package_name <?php //include Diffie Hellman functions require_once 'Crypt/DiffieHellman.php'; //set the required options for two subjects $subject_1 = array('prime'=>'123', 'generator'=>'7', 'private'=>'3'); $subject_2 = array('prime'=>'123', 'generator'=>'7', 'private'=>'34'); //apply Diffie Hellman algorithm $subject_1_GK = new Crypt_DiffieHellman( $subject_1['prime'], $subject_1['generator'], $subject_1['private']); $subject_2_GK = new Crypt_DiffieHellman( $subject_2['prime'], $subject_2['generator'], $subject_2['private']); //generate keys $subject_1_GK->generateKeys(); $subject_2_GK->generateKeys(); //compute the secret keys $subject_1_SK = $subject_1_GK->computeSecretKey( $subject_2_GK->getPublicKey())->getSharedSecretKey(); $subject_2_SK = $subject_2_GK->computeSecretKey( $subject_1_GK->getPublicKey())->getSharedSecretKey(); //displaying the secret keys echo('Subject_1_SK:'.$subject_1_SK.'<br />'); echo('Subject_2_SK:'.$subject_2_SK); ?> <?php //include Diffie Hellman functions require_once 'Crypt/DiffieHellman.php'; //set the required options for two subjects $subject_1 = array('prime' => '9568094558049898340935098349053', 'generator'=>'2', 'private' => '2232370277237628823279273723742872289398723'); $subject_2 = array('prime' => '9568094558049898340935098349053', 'generator'=>'2', 'private' => '0389237288721323987429834389298232433363463'); //apply Diffie Hellman algorithm $subject_1_GK = new Crypt_DiffieHellman( $subject_1['prime'], $subject_1['generator'], $subject_1['private']); $subject_2_GK = new Crypt_DiffieHellman( $subject_2['prime'], $subject_2['generator'], $subject_2['private']); //generate keys $subject_1_GK->generateKeys(); $subject_2_GK->generateKeys(); //compute the secret keys using BINARY mode $subject_1_SK = $subject_1_GK->computeSecretKey( $subject_2_GK->getPublicKey(Crypt_DiffieHellman::BINARY), Crypt_DiffieHellman::BINARY)-> getSharedSecretKey(Crypt_DiffieHellman::BINARY); $subject_2_SK = $subject_2_GK->computeSecretKey( $subject_1_GK->getPublicKey(Crypt_DiffieHellman::BINARY), Crypt_DiffieHellman::BINARY)-> getSharedSecretKey(Crypt_DiffieHellman::BINARY); //display the secret keys echo('subject_1_SK:'.$subject_1_SK.'<br />'); echo('subject_2_SK:'.$subject_2_SK.'<br />'); ?> 著者紹介Octavia Andreea Anghel(Octavia Andreea Anghel)
経験豊富なPHP開発者。現在は、国内外のソフトウェア開発コンテストに参加するプログラミングチームの主任トレーナーを務める。国レベルの教育プロジェクト開発のコンサルティングも担当している。共著書に『XML technologies?XML in Java』があり、XML部分の執筆を担当。PHPやXMLのほか、ソフトウェアアーキテクチャ、Webサービス、UML、ハイパフォーマンスな単体テストについても関心を寄せている。
関連記事 最新トップニュース
|
【ケータイ USA】新しい iPod は来週火曜に発表されるだろう(9月6日 13:00)
ソフトバンクモバイル、8月の純増数は約16万件――携帯電話契約数に関する速報(9月5日 14:40)
なぜ勝った? 世界No.1シェアをつかんだ“Windows”(9月5日 11:00)
Apple が『iPod』関連の発表を準備中、内容は如何に(9月4日 12:40)
TCA、8月度の携帯契約数を発表――ソフトバンクが16か月連続純増 No.1 に(9月5日 18:00)
私の周りは“geek out”している人ばかり(9月5日)
|