セキュリティに関する本では、通常、暗号化について言及する必要があります。この本の主要部分で暗号化を無視する理由は、暗号化の用途が限定的であり、開発者はセキュリティについてより広い視野で考える必要があるからです。暗号化に過度に依存すると、問題の原因がわかりにくくなることがよくあります。暗号化自体は効果的ですが、暗号化することで魔法のようにアプリケーションの安全性が高まるわけではありません。
PHP 開発者は、主に次の暗号化方式に精通している必要があります:
l 対称暗号化
l 非対称暗号化 (公開鍵)
l ハッシュ関数 (情報の概要)
l メッセージ確認コード
この付録では主に、mcrypt 拡張機能を使用した対称暗号化アルゴリズムに焦点を当てます。参照する必要がある情報は次のとおりです:
Applied Cryptography、Bruce Schneier 著 (ワイリー)
http://www.php.cn/
http://www.php.cn/
http://www.php.cn/
http ://www.php.cn/
http://www.php.cn/
C.1. パスワードの保管
パスワードをデータベースに保存する場合は、パスワードを平文のまま保存しないでください。代わりに、パスワードのハッシュ値を保存し、次の文字列を追加して使用してください。
パスワードが正しいかどうかを確認する必要がある場合は、ハッシュ値を計算します。同じようにして、類似点と相違点を比較します。
<?php /* $password contains the password. */ $salt = 'SHIFLETT'; $password_hash = md5($salt . md5($password . $salt)); /* Store password hash. */ ?>
ハッシュ値がまったく同じである場合、その理由はパスワードも同じであるためです。同じ。
このトリックが使用されると、ユーザーにパスワードを伝えることは不可能になります。ユーザーがパスワードを忘れた場合、新しいパスワードを入力し、ハッシュ値を再計算してデータベースに保存するよう求めることしかできません。もちろん、ユーザーの認証には細心の注意を払う必要があります。パスワード リマインダーは頻繁に攻撃の対象となり、セキュリティ侵害の原因にもなります。
C.2. mcrypt を使用する
PHP の標準暗号化拡張機能は mcrypt で、さまざまな暗号化アルゴリズムをサポートしています。 mcrypt_list_algorithms( ) 関数を使用して、プラットフォームでサポートされているアルゴリズムのリストを表示します:
<?php $salt = 'SHIFLETT'; $password_hash = md5($salt . md5($_POST['password'] . $salt)); /* Compare password hashes. */ ?>
暗号化と復号化は、それぞれ mcrypt_encrypt( ) と mcrypt_decrypt( ) によって実行されます。 ) 実装する関数。どちらの関数にも 5 つのパラメーターがあり、最初のパラメーターは使用するアルゴリズムを指定するために使用されます:
<?php echo '<pre class="brush:php;toolbar:false">' . print_r(mcrypt_list_algorithms(), TRUE) . ''; ?>
暗号化キー (2 番目のパラメーター) は非常に機密データであるため、必ず安全な場所に保管する必要があります。暗号化キーは、第 8 章のデータベース権限を保護する方法を使用して保護できます。経済状況が許せば、非常に強力なセキュリティを提供するハードウェア暗号化キーが最良の選択です。
この関数には複数のモードから選択でき、mcrypt_list_modes(
) サポートされているすべてのモードをリストするには:
<?php mcrypt_encrypt($algorithm, $key, $cleartext, $mode, $iv); mcrypt_decrypt($algorithm, $key, $ciphertext, $mode, $iv); ?>
5 番目のパラメーター ($iv) は、mcrypt_create_iv() 関数を使用して作成できる初期化ベクトルです。
次のサンプル クラスは、基本的な暗号化および復号化メソッドを提供します。
上面的类会在其它示例中使用,下面是它的使用方法示例:
<?php $crypt = new crypt(); $crypt->cleartext = 'This is a string'; $crypt->generate_iv(); $crypt->encrypt(); $ciphertext = base64_encode($crypt->ciphertext); $iv = base64_encode($crypt->iv); unset($crypt); /* Store $ciphertext and $iv (initialization vector). */ $ciphertext = base64_decode($ciphertext); $iv = base64_decode($iv); $crypt = new crypt(); $crypt->iv = $iv; $crypt->ciphertext = $ciphertext; $crypt->decrypt(); $cleartext = $crypt->cleartext; ?>
小提示
本扩展要求你在编译PHP时使用-mcrypt标识。安装指南及要求详见http://www.php.cn/。
C.3. 信用卡号的保存
我常常被问到如何安全地保存信用卡号。我的总是会首先询问他们是否确实有必要保存信用卡号。毕竟不管具体是如何操作的,引入不必要的风险是不明智的。同时国家法律还有关于信用卡信息处理方面的规定,我还时刻小心地提醒我并不是一个法律专家。
本书中我并不会专门讨论信用卡处理的方法,而是会说明如何保存加密信息到数据库及在读取时解密。该流程会导致系统性能的下降,但是确实提供了一层保护措施。其主要优点是如果数据库内容泄密暴露出的只是加密信息,但是前提是加密键是安全的。因此,加密键与加密的实现方法本身同样重要。
保存加密数据到数据的过程是,首先加密数据,然后通过初始向量与明文建立密文来保存到数据库。由于密文是二进制字符串,还需要通过base64_encode( )转换成普通文本字符串以保证二进制编码的安全存储。
<?php $crypt = new crypt(); $crypt->cleartext = '1234567890123456'; $crypt->generate_iv(); $crypt->encrypt(); $ciphertext = $crypt->ciphertext; $iv = $crypt->iv; $string = base64_encode($iv . $ciphertext); ?>
保存该字串至数据库。在读取时,则是上面流程的逆处理:
<?php $string = base64_decode($string); $iv_size = mcrypt_get_iv_size($algorithm, $mode); $ciphertext = substr($string, $iv_size); $iv = substr($string, 0, $iv_size); $crypt = new crypt(); $crypt->iv = $iv; $crypt->ciphertext = $ciphertext; $crypt->decrypt(); $cleartext = $crypt->cleartext; ?>
本实现方法假定加密算法与模式不变。如果它们是不定的话,你还要保存它们以用于解密数据。加密键是唯一需要保密的数据。
C.4. 加密会话数据
如果你的数据库存在安全问题,或者部分保存在会话中的数据是敏感的,你可能希望加密会话数据。除非很有必要,一般我不推荐这样做,但是如果你觉得在你的情形下需要这样做的话,本节提供了一个实现方法的示例。
这个方案十分简单。实际上,在第八章中,已经说明了如何通过调用session_set_save_handler( )来执行你自己的会话机制。通过对保存和读取数据的函数的少量调整,你就能加密存入数据库的数据及在读取时解密数据:
<?php function _read($id) { global $_sess_db; $algorithm = MCRYPT_BLOWFISH; $mode = MCRYPT_MODE_CBC; $id = mysql_real_escape_string($id); $sql = "SELECT data FROM sessions WHERE id = '$id'"; if ($result = mysql_query($sql, $_sess_db)) { $record = mysql_fetch_assoc($result); $data = base64_decode($record['data']); $iv_size = mcrypt_get_iv_size($algorithm, $mode); $ciphertext = substr($data, $iv_size); $iv = substr($data, 0, $iv_size); $crypt = new crypt(); $crypt->iv = $iv; $crypt->ciphertext = $ciphertext; $crypt->decrypt(); return $crypt->cleartext; } return ''; } function _write($id, $data) { global $_sess_db; $access = time(); $crypt = new crypt(); $crypt->cleartext = $data; $crypt->generate_iv(); $crypt->encrypt(); $ciphertext = $crypt->ciphertext; $iv = $crypt->iv; $data = base64_encode($iv . $ciphertext); $id = mysql_real_escape_string($id); $access = mysql_real_escape_string($access); $data = mysql_real_escape_string($data); $sql = "REPLACE INTO sessions VALUES ('$id', '$access', '$data')"; return mysql_query($sql, $_sess_db); }
以上就是PHP安全-加密的内容,更多相关内容请关注PHP中文网(www.php.cn)!