数据加密在我们生活中的地位已经越来越重要了,尤其是考虑到在网络上发生的大量交易和传输的大量数据。如果对于采用安全措施有兴趣的话,也一定会有兴趣了解PHP提供的一系列安全功能。在本篇文章中,我们将介绍这些功能,提供一些基本的用法,以便你能够为自己的应用软件中增加安全功能。
预备知识
在详细介绍PHP的安全功能之前,我们需要花点时间来向没有接触过这方面内容的读者介绍一些有关密码学的基本知识,如果对密码学的基本概念已经非常熟悉,就可以跳过去这一部分。
密码学可以通俗地被描述为对加/解密的研究和实验,加密是将易懂的资料转换为不易懂资料的过程,解密则是将不易懂的资料转换为原来易懂资料的过程。不易懂的资料被称作密码,易懂的资料被称作明码。
数据的加/解密都需要一定的算法,这些算法可以非常地简单,如著名的凯撒码,但当前的加密算法要相对复杂得多,其中一些利用现有的方法甚至是无法破译的。
PHP的加密功能
只要有一点使用非Windows平台经验的人可能对crypt()也相当熟悉,这一函数完成被称作单向加密的功能,它可以加密一些明码,但不能够将密码转换为原来的明码。尽管从表面上来看这似乎是一个没有什么用处的功能,但它的确被广泛用来保证系统密码的完整性。因为,单向加密的口令一旦落入第三方人的手里,由于不能被还原为明文,因此也没有什么大用处。在验证用户输入的口令时,用户的输入采用的也是单向算法,如果输入与存储的经加密后的口令相匹配,则输入的口信一定是正确的。
PHP同样提供了使用其crypt()函数完成单向加密功能的可能性。我将在这里简要地介绍该函数:
string crypt (string input_string [, string salt])
其中的input_string参数是需要加密的字符串,第二个可选的salt是一个位字串,它能够影响加密的暗码,进一步地排除被称作预计算攻击的可能性。缺省情况下,PHP使用一个2个字符的DES干扰串,如果你的系统使用的是MD5(我将在以后介绍MD5算法),它会使用一个12个字符的干扰串。顺便说一下,可以通过执行下面的命令发现系统将要使用的干扰串的长度:
print "My system salt size is: ". CRYPT_SALT_LENGTH;
系统也可能支持其他的加密算法。crypt()支持四种算法,下面是它支持的算法和相应的salt参数的长度:
算法 Salt长度
CRYPT_STD_DES 2-character (Default)
CRYPT_EXT_DES 9-character
CRYPT_MD5 12-character beginning with 102/td
CRYPT_BLOWFISH 16-character beginning with 102/td
用crypt()实现用户身份验证
作为crypt()函数的一个例子,考虑这样一种情况,你希望创建一段PHP脚本程序限制对一个目录的访问,只允许能够提供正确的用户名和口令的用户访问这一目录。我将把资料存储在我喜欢的数据库MySQL的一个表中。下面我们以创建这个被称作members的表开始我们的例子:
mysqlCREATE TABLE members (
-username CHAR(14) NOT NULL,
-password CHAR(32) NOT NULL,
-PRIMARY KEY(username)
-);
然后,我们假定下面的数据已经存储在该表中:
用户名 密码
clark keloD1C377lKE
bruce ba1T7vnz9AWgk
peter paLUvRWsRLZ4U
这些加密的口令对应的明码分别是kent、banner和parker。注意一下每个口令的前二个字母,这是因为我使用了下面的代码,根据口令的前二个字母创建干扰串的:
.
= substr(, 0, 2);
= crypt(, );
// 然后就和用户名一起存储在MySQL中
我将使用Apache的口令-应答认证配置提示用户输入用户名和口令,一个鲜为人知的有关PHP的信息是,它可以把Apache的口令-应答系统输入的用户名和口令识别为和,我将在身份验证脚本中用到这二个变量。花一些时间仔细阅读下面的脚本,多注意一下其中的解释,以便更好地理解下面的代码:
crypt()和Apache的口令-应答验证系统的应用
<?php
= "localhost";
= "zorro";
= "hellodolly";
= "users";
// Set authorization to False
= 0;
// Verify that user has entered username and password
if (isset() && isset()) :
mysql_pconnect(, , ) or die("Can't connect to MySQL
server!");
mysql_select_db() or die("Can't select database!");
// Perform the encryption
= substr(, 0, 2);
= crypt(, );
// Build the query
= "SELECT username FROM members WHERE
username = '' AND
password = ''";
// Execute the query
if (mysql_numrows(mysql_query()) == 1) :
= 1;
endif;
endif;
// confirm authorization
if (! ) :
header('WWW-Authenticate: Basic realm="Private"');
header('HTTP/1.0 401 Unauthorized');
print "You are unauthorized to enter this area.";
exit;
else :
print "This is the secret data!";
endif;
?
上面就是一个核实用户访问权限的简单身份验证系统。在使用crypt()保护重要的机密资料时,记住在缺省状态下使用的crypt()并不是最安全的,只能用在对安全性要求较低的系统中,如果需要较高的安全性能,就需要我在本篇文章的后面介绍的算法。
下面我将介绍另一个PHP支持的函数━━md5(),这一函数使用MD5散列算法,它有几种很有趣的用法值得一提:
混编
一个混编函数可以将一个可变长度的信息变换为具有固定长度被混编过的输出,也被称作“信息文摘”。这是十分有用的,因为一个固定长度的字符串可以用来检查文件的完整性和验证数字签名以及用户身份验证。由于它适合于PHP,PHP内置的md5()混编函数将把一个可变长度的信息转换为128位(32个字符)的信息文摘。混编的一个有趣的特点是不能通过分析混编后的信息得到原来的明码,因为混编后的结果与原来的明码内容没有依赖关系。 即便只改变一个字符串中的一个字符,也将使得MD5混编算法计算出二个截然不同的结果。我们首先来看下表的内容及其相应的结果:
使用md5()混编字符串
<?php
= "This is some message that I just wrote";
= md5();
print "hash: ";
?
结果:
hash: 81ea092649ca32b5ba375e81d8f4972c
注意,结果的长度为32个字符。再来看一下下面的表,其中的的值有了一点微小的变化:
使用md5()对一个稍微变化的字符串进行混编
<?php
//注意,message中少了一个s
= "This is some mesage that I just wrote";
= md5();
print "hash2: <br /<br /";
?
结果:
hash2: e86cf511bd5490d46d5cd61738c82c0c
可以发现,尽管二个结果的长度都是32个字符,但明文中一点微小的变化使得结果发生了很大的变化,因此,混编和md5()函数是检查数据中微小变化的一个很好的工具。
尽管crypt()和md5()各有用处,但二者在功能上都受到一定的限制。在下面的部分中,我们将介绍二个非常有用的被称作Mcrypt和Mhash的PHP扩展,将大大拓展PHP用户在加密方面的选择。
尽管我们在上面的小节中说明了单向加密的重要性,但有时我们可能需要在加密后,再把密码数据还原成原来的数据,幸运的是,PHP通过Mcrypt扩展库的形式提供了这种可能性。
Mcrypt
Mcrypt 2.5.7 Unix | Win32
Mcrypt 2.4.7是一个功能强大的加密算法扩展库,它包括有22种算法,其中就包括下面的几种算法:
Blowfish RC2 Safer-sk64 xtea
Cast-256 RC4 Safer-sk128
DES RC4-iv Serpent
Enigma Rijndael-128 Threeway
Gost Rijndael-192 TripleDES
LOKI97 Rijndael-256 Twofish
PanamaSaferplus Wake
安装:
在标准的PHP软件包中不包括Mcrypt,因此需要下载它,下载的地址为:ftp://argeas.cs-net.gr/pub/unix/mcrypt/。下载后,按照下面的方法进行编译,并把它扩充在PHP中:
下载Mcrypt软件包。
gunzipmcrypt-x.x.x.tar.gz
tar -xvfmcrypt-x.x.x.tar
./configure --disable-posix-threads
make
make install
cd to your PHP directory.
./configure -with-mcrypt=[dir] [--other-configuration-directives]
make
make install
当然了,根据你的要求和PHP安装时与互联网服务器软件的关系,上面的过程可能需要作适当的修改。
使用Mcrypt
Mcrypt的优点不仅仅在于其提供的加密算法较多,还在于它可以对数据进行加/解密处理,此外,它还提供了35种处理数据用的函数。尽管对这些函数进行详细介绍已经超出了这篇文章的范围,我还是要就几个典型的函数作一下简要的介绍。
首先,我将介绍如何使用Mcrypt扩展库对数据进行加密,然后再介绍如何使用它进行解密。下面的代码对这一过程进行了演示,首先是对数据进行加密,然后在浏览器上显