En tant que livre sur la sécurité, le chiffrement est généralement un sujet qui doit être mentionné. La raison pour laquelle j’ignore le chiffrement dans la partie principale de ce livre est que son utilisation est restreinte et que les développeurs devraient penser à la sécurité dans une perspective plus large. Une dépendance excessive au chiffrement obscurcit souvent la source du problème. Bien que le chiffrement lui-même soit efficace, il ne rend pas comme par magie une application plus sécurisée.
Un développeur PHP doit principalement être familier avec les méthodes de chiffrement suivantes :
l Cryptage symétrique
l Cryptage asymétrique (clé publique)
l Fonction de hachage (résumé des informations)
l Code de vérification des informations
Cette annexe se concentre principalement sur l'algorithme de chiffrement symétrique utilisant l'extension mcrypt. Les informations auxquelles vous devez vous référer sont les suivantes :
Cryptographie appliquée, par Bruce Schneier (Wiley)
http://www.php.cn/
http://www.php.cn/
http://www.php.cn/
http://www.php.cn/
http://www.php.cn/
C.1. Stockage du mot de passe
Lorsque vous stockez des mots de passe dans une base de données, ne les stockez jamais en clair. Stockez plutôt le hachage du mot de passe et utilisez la chaîne ajoutée :
<?php /* $password contains the password. */ $salt = 'SHIFLETT'; $password_hash = md5($salt . md5($password . $salt)); /* Store password hash. */ ?>
Lorsque vous devez confirmer si un mot de passe est correct, utilisez la même méthode Calculez le valeur de hachage et comparer les similitudes et les différences :
<?php $salt = 'SHIFLETT'; $password_hash = md5($salt . md5($_POST['password'] . $salt)); /* Compare password hashes. */ ?>
Si les valeurs de hachage sont exactement les mêmes, vous avez des raisons de penser que les mots de passe sont également les mêmes.
Si cette astuce est utilisée, il est impossible de dire à l'utilisateur quel est son mot de passe. Lorsqu'un utilisateur oublie son mot de passe, vous pouvez uniquement lui demander de saisir un nouveau mot de passe, de recalculer la valeur de hachage et de la stocker dans la base de données. Bien entendu, vous devez être très prudent lors de l’authentification des utilisateurs : les rappels de mots de passe sont une cible fréquente d’attaques et une source fréquente de failles de sécurité.
C.2. Utiliser mcrypt
L'extension de chiffrement standard de PHP est mcrypt, qui prend en charge de nombreux algorithmes de chiffrement différents. Vous pouvez transmettre mcrypt_list_algorithms( ) pour voir la liste des algorithmes pris en charge sur votre plateforme :
<?php echo '<pre class="brush:php;toolbar:false">' . print_r(mcrypt_list_algorithms(), TRUE) . ''; ?>
Le cryptage et le déchiffrement sont respectivement gérés par mcrypt_encrypt() et mcrypt_decrypt( ) fonction à implémenter. Les deux fonctions ont 5 paramètres. Le premier paramètre permet de préciser l'algorithme utilisé :
<?php mcrypt_encrypt($algorithm, $key, $cleartext, $mode, $iv); mcrypt_decrypt($algorithm, $key, $ciphertext, $mode, $iv); ?>
.
La clé de cryptage (le deuxième paramètre) est une donnée très sensible, vous voulez donc vous assurer de la stocker dans un endroit sûr. Les clés de chiffrement peuvent être protégées à l'aide des méthodes de protection des autorisations de base de données décrites au chapitre 8. Si les conditions financières le permettent, les clés de chiffrement matérielles constituent le meilleur choix, car elles offrent une sécurité extrêmement renforcée.
La fonction propose plusieurs modes, vous pouvez utiliser mcrypt_list_modes( ) pour lister tous les modes pris en charge :
<?php echo '<pre class="brush:php;toolbar:false">' . print_r(mcrypt_list_modes(), TRUE) . ''; ?>
Le le cinquième paramètre ($iv) est le vecteur d'initialisation, qui peut être créé à l'aide de la fonction mcrypt_create_iv().
L'exemple de classe suivant fournit des méthodes de chiffrement et de déchiffrement de base :
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 $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)!