PHP提供了使用其crypt()函数完成单向加密功能的可能性。 string crypt (string input_string [, string salt]) 其中的input_string参数是需要加密的字符串,第二个可选的salt是一个位字串,它能够影响加密的暗码,进一步地排除被称作预计算攻击的可能性。缺省情况下,PHP使用一个2个字符的DES干扰串,如果你的系统使用的是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 $1$ CRYPT_BLOWFISH 16-character beginning with $2$ 用crypt()实现用户身份验证 作为crypt()函数的一个例子,考虑这样一种情况,你希望创建一段PHP脚本程序限制对一个目录的访问,只允许能够提供正确的用户名和口令的用户访问这一目录。我将把资料存储在我喜欢的数据库MySQL的一个表中。下面我们以创建这个被称作members的表开始我们的例子: mysql>CREATE TABLE members ( ->username CHAR(14) NOT NULL, ->password CHAR(32) NOT NULL, ->PRIMARY KEY(username) ->); 然后,我们假定下面的数据已经存储在该表中: 用户名 密码 clark keloD1C377lKE bruce ba1T7vnz9Awgk peter paLUvRWsRLZ4U 这些加密的口令对应的明码分别是kent、banner和parker。注意一下每个口令的前二个字母,这是因为我使用了下面的代码,根据口令的前二个字母创建干扰串的: $enteredPassword. $salt = substr($enteredPassword, 0, 2); $userPswd = crypt($enteredPassword, $salt); // $userPswd然后就和用户名一起存储在MySQL中 我将使用Apache的口令-应答认证配置提示用户输入用户名和口令,一个鲜为人知的有关PHP的信息是,它可以把Apache的口令-应答系统输入的用户名和口令识别为$PHP_AUTH_USER和$PHP_AUTH_PW,我将在身份验证脚本中用到这二个变量。 crypt()和Apache的口令-应答验证系统的应用 <?php $host = "localhost"; $user = "zorro"; $pswd = "hellodolly"; $db = "users"; // Set authorization to False $authorization = 0; // Verify that user has entered username and password if (isset($PHP_AUTH_USER) && isset($PHP_AUTH_PW)) : mysql_pconnect($host, $user, $pswd) or die("Can't connect to MySQL server!"); mysql_select_db($db) or die("Can't select database!"); // Perform the encryption $salt = substr($PHP_AUTH_PW, 0, 2); $encrypted_pswd = crypt($PHP_AUTH_PW, $salt); // Build the query $query = "SELECT username FROM members WHERE username = '$PHP_AUTH_USER' AND password = '$encrypted_pswd'"; // Execute the query if (mysql_numrows(mysql_query($query)) == 1) : $authorization = 1; endif; endif; // confirm authorization if (! $authorization) : 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 $msg = "This is some message that I just wrote"; $enc_msg = md5($msg); print "hash: $enc_msg "; ?> 结果: hash: 81ea092649ca32b5ba375e81d8f4972c 注意,结果的长度为32个字符。再来看一下下面的表,其中的$msg的值有了一点微小的变化: 使用md5()对一个稍微变化的字符串进行混编 <?php //注意,message中少了一个s $msg = "This is some mesage that I just wrote"; $enc_msg = md5($msg); print "hash2: $enc_msg <br /><br />"; ?> 结果: hash2: e86cf511bd5490d46d5cd61738c82c0c 可以发现,尽管二个结果的长度都是32个字符,但明文中一点微小的变化使得结果发生了很大的变化,因此,混编和md5()函数是检查数据中微小变化的一个很好的工具。 尽管crypt()和md5()各有用处,但二者在功能上都受到一定的限制。
|