PHP 開発者は主に次の暗号化方式に精通している必要があります:
l 対称暗号化
l . アウト アウト オフ アウトの ''s '' のホルダーの ‐ ‐‐ ‐‐‐ ‐
この付録では、mcrypt 拡張機能を使用した対称暗号化アルゴリズムに焦点を当てています。参照する必要がある情報は次のとおりです。
Applied Cryptography、Bruce Schneier (Wiley) 著
http://www.schneier.com/blog/
http://wikipedia.org/wiki /暗号化
http://phpsec.org/articles/2005/password-hashing.html
http://pear.php.net/package/Crypt_HMAC
http://pear.php.net/package/Crypt_RSA
C.1. パスワードの保存
パスワードをデータベースに保存する場合は、パスワードのハッシュ値を保存し、同時に追加の文字列を使用してください。 パスワードが正しいかどうかを確認する必要がある場合は、同じ方法でハッシュ値を計算し、類似点と相違点を比較してください:
1 2 3 4 5 6 7 8 9 10 | <?php
$salt = 'SHIFLETT';
$password_hash = md5( $salt . md5( $password . $salt ));
?>
|
ログイン後にコピー
ハッシュ値がまったく同じであれば、次のように考える理由があります。パスワードも同じです。
このトリックが使用されると、ユーザーにパスワードを伝えることは不可能になります。ユーザーがパスワードを忘れた場合、新しいパスワードを入力し、ハッシュ値を再計算してデータベースに保存するよう求めることしかできません。もちろん、ユーザーの認証には細心の注意を払う必要があります。パスワード リマインダーは頻繁に攻撃の対象となり、セキュリティ侵害の原因にもなります。
C.2. mcrypt の使用
PHP の標準暗号化拡張機能は mcrypt であり、さまざまな暗号化アルゴリズムをサポートしています。 mcrypt_list_algorithms() 関数を通じて、プラットフォームでサポートされているアルゴリズムのリストを表示できます。
1 2 3 4 5 6 7 8 | <?php
$salt = 'SHIFLETT';
$password_hash = md5( $salt . md5( $_POST ['password'] . $salt ));
?>
|
ログイン後にコピー
暗号化と復号化は、それぞれ mcrypt_encrypt() 関数と mcrypt_decrypt() 関数によって実装されます。どちらの関数にも 5 つのパラメーターがあり、最初のパラメーターは使用するアルゴリズムを指定するために使用されます:
1 2 3 | <?php
echo '<pre class = "brush:php;toolbar:false" >' . print_r(mcrypt_list_algorithms(), TRUE) . '
|
';
?>
ログイン後にコピー
暗号化キー (2 番目のパラメーター) は非常に機密データであるため、必ず安全な場所に保管する必要があります。暗号化キーは、第 8 章のデータベース権限を保護する方法を使用して保護できます。経済状況が許せば、非常に強力なセキュリティを提供するハードウェア暗号化キーが最良の選択です。
この関数には複数のモードから選択できます。 mcrypt_list_modes() を使用して、サポートされているすべてのモードをリストできます:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?php
mcrypt_encrypt( $algorithm ,
$key ,
$cleartext ,
$mode ,
$iv );
mcrypt_decrypt( $algorithm ,
$key ,
$ciphertext ,
$mode ,
$iv );
?>
|
ログイン後にコピー
5 番目のパラメーター ($iv) は、mcrypt_create_iv() 関数を使用して作成できる初期化ベクトルです。 。
次のクラス例は、基本的な暗号化および復号化メソッドを提供します:
1 2 3 | <?php
echo '<pre class = "brush:php;toolbar:false" >' . print_r(mcrypt_list_modes(), TRUE) . '
|
';
?>
ログイン後にコピー
上記のクラスは他の例で使用されます。以下はその使用例です:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | class crypt
{
private $algorithm ;
private $mode ;
private $random_source ;
public $cleartext ;
public $ciphertext ;
public $iv ;
public function __construct( $algorithm = MCRYPT_BLOWFISH,
$mode = MCRYPT_MODE_CBC,
$random_source = MCRYPT_DEV_URANDOM)
{
$this ->algorithm = $algorithm ;
$this ->mode = $mode ;
$this ->random_source = $random_source ;
}
public function generate_iv()
{
$this ->iv = mcrypt_create_iv(mcrypt_get_iv_size( $this ->algorithm,
$this ->mode), $this ->random_source);
}
public function encrypt()
{
$this ->ciphertext = mcrypt_encrypt( $this ->algorithm,
$_SERVER ['CRYPT_KEY'], $this ->cleartext, $this ->mode, $this ->iv);
}
public function decrypt()
{
$this ->cleartext = mcrypt_decrypt( $this ->algorithm,
$_SERVER ['CRYPT_KEY'], $this ->ciphertext, $this ->mode, $this ->iv);
}
}
?>
|
ログイン後にコピー
ヒント
この拡張機能には次のものが必要です。 PHP をコンパイルするときに -mcrypt フラグを使用します。インストール手順と要件については、http://php.net/mcrypt を参照してください。
C.3. クレジット カード番号の保存
クレジット カード番号を安全に保存する方法についてよく質問されます。私の場合はいつも、クレジット カード番号を本当に保存する必要があるかどうかを尋ねることから始まります。結局のところ、どのように行うとしても、不必要なリスクを持ち込むのは賢明ではありません。同時に、国内法にもクレジットカード情報の処理に関する規制があり、私は法律の専門家ではないことを常に自分に言い聞かせています。
この本では、クレジットカードの処理方法については特に説明しませんが、暗号化された情報をデータベースに保存し、読み取り時に復号化する方法について説明します。このプロセスによりシステムのパフォーマンスが低下しますが、保護層は提供されます。その主な利点は、データベースのコンテンツが侵害された場合に、暗号化された情報のみが公開されることですが、その前提として暗号化キーが安全であることが挙げられます。したがって、暗号化キーは暗号化自体の実装と同じくらい重要です。
暗号化されたデータをデータに保存するプロセスは、まずデータを暗号化し、次に初期ベクトルと平文を通じて暗号文を作成し、データベースに保存します。暗号文はバイナリ文字列であるため、バイナリ エンコードを安全に保存するには、base64_encode() を通じて通常のテキスト文字列に変換する必要があります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <?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 );
$ciphertext = base64_decode ( $ciphertext );
$iv = base64_decode ( $iv );
$crypt = new crypt();
$crypt ->iv = $iv ;
$crypt ->ciphertext = $ciphertext ;
$crypt ->decrypt();
$cleartext = $crypt ->cleartext;
?>
|
ログイン後にコピー
文字列をデータベースに保存します。読み込み時は上記の逆の処理になります:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <?php
$crypt = new crypt();
$crypt ->cleartext = '1234567890123456';
$crypt ->generate_iv();
$crypt ->encrypt();
$ciphertext = $crypt ->ciphertext;
$iv = $crypt ->iv;
$string = base64_encode ( $iv . $ciphertext );
?>
|
ログイン後にコピー
この実装方法は、暗号化アルゴリズムとモードが変更されていないことを前提としています。定義されていない場合は、データの復号化に使用するために保存する必要もあります。暗号化キーは、秘密にしておく必要がある唯一のデータです。
C.4. セッションデータを暗号化する
如果你的数据库存在安全问题,或者部分保存在会话中的数据是敏感的,你可能希望加密会话数据。除非很有必要,一般我不推荐这样做,但是如果你觉得在你的情形下需要这样做的话,本节提供了一个实现方法的示例。
这个方案十分简单。实际上,在第八章中,已经说明了如何通过调用session_set_save_handler( )来执行你自己的会话机制。通过对保存和读取数据的函数的少量调整,你就能加密存入数据库的数据及在读取时解密数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | <?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 );
}
?>
|
ログイン後にコピー