Heim > Artikel > Backend-Entwicklung > PHP-Sicherheitsverschlüsselung
Als Buch über Sicherheit ist die Verschlüsselung normalerweise ein Thema, das erwähnt werden muss. Der Grund, warum ich die Verschlüsselung im Hauptteil dieses Buches ignoriere, liegt darin, dass ihr Einsatzbereich begrenzt ist und Entwickler die Sicherheit im größeren Zusammenhang betrachten sollten. Eine übermäßige Abhängigkeit von der Verschlüsselung verschleiert oft die Ursache des Problems. Obwohl die Verschlüsselung an sich effektiv ist, macht sie eine Anwendung nicht auf magische Weise sicherer.
Ein PHP-Entwickler sollte vor allem mit den folgenden Verschlüsselungsmethoden vertraut sein:
l Symmetrische Verschlüsselung
l Asymmetrische Verschlüsselung (öffentlicher Schlüssel)
l Hash-Funktion (Informationszusammenfassung)
l Informationsüberprüfungscode
Dieser Anhang konzentriert sich hauptsächlich auf den symmetrischen Verschlüsselungsalgorithmus unter Verwendung der mcrypt-Erweiterung. Die Informationen, auf die Sie sich beziehen müssen, lauten wie folgt:
Applied Cryptography, von Bruce Schneier (Wiley)
http://www.php.cn/
http://www.php.cn/
http://www.php.cn/
http://www.php.cn/
http://www.php.cn/
Passwortspeicherung
Wenn Sie Passwörter in einer Datenbank speichern, speichern Sie sie niemals im Klartext. Speichern Sie stattdessen den Hash des Passworts und verwenden Sie die angehängte Zeichenfolge:
<?php /* $password contains the password. */ $salt = 'SHIFLETT'; $password_hash = md5($salt . md5($password . $salt)); /* Store password hash. */ ?>
Wenn Sie bestätigen müssen, ob ein Passwort korrekt ist, verwenden Sie dieselbe Methode Berechnen Sie den Hashwert und vergleichen Sie die Ähnlichkeiten und Unterschiede:
<?php $salt = 'SHIFLETT'; $password_hash = md5($salt . md5($_POST['password'] . $salt)); /* Compare password hashes. */ ?>
Wenn die Hashwerte genau gleich sind, haben Sie Grund zu der Annahme, dass auch die Passwörter gleich sind.
Wenn dieser Trick angewendet wird, ist es unmöglich, dem Benutzer sein Passwort mitzuteilen. Wenn ein Benutzer sein Passwort vergisst, können Sie ihn nur bitten, ein neues Passwort einzugeben und den Hash-Wert neu zu berechnen und in der Datenbank zu speichern. Natürlich müssen Sie bei der Authentifizierung von Benutzern sehr vorsichtig sein – Passwort-Erinnerungen sind ein häufiges Ziel von Angriffen und eine häufige Quelle von Sicherheitsverletzungen.
C.2. Verwenden Sie mcrypt
Die Standard-Verschlüsselungserweiterung von PHP ist mcrypt, die viele verschiedene Verschlüsselungsalgorithmen unterstützt. Sie können mcrypt_list_algorithms( übergeben )-Funktion, um die Liste der unterstützten Algorithmen auf Ihrer Plattform anzuzeigen:
<?php echo '<pre class="brush:php;toolbar:false">' . print_r(mcrypt_list_algorithms(), TRUE) . ''; ?>
Verschlüsselung und Entschlüsselung werden jeweils von mcrypt_encrypt() und mcrypt_decrypt( übernommen. ) Funktion zur Implementierung. Beide Funktionen haben 5 Parameter. Der erste Parameter wird verwendet, um den verwendeten Algorithmus anzugeben:
<?php mcrypt_encrypt($algorithm, $key, $cleartext, $mode, $iv); mcrypt_decrypt($algorithm, $key, $ciphertext, $mode, $iv); ?>
Beim Verschlüsselungsschlüssel (zweiter Parameter) handelt es sich um sehr sensible Daten, daher sollten Sie sicherstellen, dass Sie ihn an einem sicheren Ort aufbewahren. Verschlüsselungsschlüssel können mit den Methoden zum Schutz von Datenbankberechtigungen in Kapitel 8 geschützt werden. Wenn die finanziellen Bedingungen es zulassen, sind Hardware-Verschlüsselungsschlüssel die beste Wahl, da sie eine extrem starke Sicherheit bieten.
Die Funktion verfügt über mehrere Modi zur Auswahl, Sie können mcrypt_list_modes( verwenden ), um alle unterstützten Modi aufzulisten:
<?php echo '<pre class="brush:php;toolbar:false">' . print_r(mcrypt_list_modes(), TRUE) . ''; ?>
Die Der fünfte Parameter ($iv) ist der Initialisierungsvektor, der mit der Funktion mcrypt_create_iv() erstellt werden kann.
Die folgende Beispielklasse stellt grundlegende Verschlüsselungs- und Entschlüsselungsmethoden bereit:
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)!