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的表开始我们的例子:

  mysql>CREATE TABLE members (

  ->username CHAR(14) NOT NULL,

  ->password CHAR(32) NOT NULL,

  ->RIMARY KEY(username)

  ->);

  然后,我们假定下面的数据已经存储在该表中:

  用户名 密码

  clark keloD1C377lKE

  bruce ba1T7vnz9AWgk

  peter paLUvRWsRLZ4U

  这些加密的口令对应的明码分别是kent、banner和parker。注意一下每个口令的前二个字母,这是因为我使用了下面的代码,根据口令的前二个字母创建干扰串的:

  .

  = substr(, 0, 2);

  = crypt(, );

  // 然后就和用户名一起存储在MySQL中

  我将使用Apache的口令-应答认证配置提示用户输入用户名和口令,一个鲜为人知的有关PHP的信息是,它可以把Apache的口令-应答系统输入的用户名和口令识别为和,我将在身份验证脚本中用到这二个变量。花一些时间仔细阅读下面的脚本,多注意一下其中的解释,以便更好地理解下面的代码:

  crypt()和Apache的口令-应答验证系统的应用

  = "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="rivate"'');

  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()混编字符串

  = "This is some message that I just wrote";

  = md5();

  print "hash: ";

  code.google.com/p/lcze

  code.google.com/p/wzze

  code.google.com/p/laze

  code.google.com/p/czze

  code.google.com/p/lfze

  code.google.com/p/whze

  code.google.com/p/qdze

  code.google.com/p/ycze

  code.google.com/p/ylze

  code.google.com/p/csbe

  code.google.com/p/hebz

  code.google.com/p/ncmi

  code.google.com/p/ykze

  code.google.com/p/xyze

  code.google.com/p/xmze

  code.google.com/p/fzme

  code.google.com/p/wzme

  code.google.com/p/sxze

  code.google.com/p/hzmi

  code.google.com/p/jnmi

  code.google.com/p/dyme

  code.google.com/p/hfme

  code.google.com/p/lami

  code.google.com/p/czme

  code.google.com/p/chuz

  code.google.com/p/zzcm

  code.google.com/p/jcze

  code.google.com/p/nbzm

  code.google.com/p/nbmi

  code.google.com/p/wzcm

  code.google.com/p/sxme

  code.google.com/p/hzme

  code.google.com/p/jhme

  code.google.com/p/jnme

  code.google.com/p/lyme

  code.google.com/p/qdbm

  code.google.com/p/whce

  code.google.com/p/dycm

  code.google.com/p/ytem

  code.google.com/p/wfem

  code.google.com/p/hzim

  ?>

  结果:

  hash: 81ea092649ca32b5ba375e81d8f4972c

  注意,结果的长度为32个字符。再来看一下下面的表,其中的的值有了一点微小的变化:

  使用md5()对一个稍微变化的字符串进行混编

  //注意,message中少了一个s

  = "This is some mesage that I just wrote";

  = md5();

  print "hash2:

  ";

  ?>

  结果:

  hash2: e86cf511bd5490d46d5cd61738c82c0c

  可以发现,尽管二个结果的长度都是32个字符,但明文中一点微小的变化使得结果发生了很大的变化,因此,混编和md5()函数是检查数据中微小变化的一个很好的工具。

  尽管crypt()和md5()各有用处,但二者在功能上都受到一定的限制。在下面的部分中,我们将介绍二个非常有用的被称作Mcrypt和Mhash的PHP扩展,将大大拓展PHP用户在加密方面的选择。

  尽管我们在上面的小节中说明了单向加密的重要性,但有时我们可能需要在加密后,再把密码数据还原成原来的数据,幸运的是,PHP通过Mcrypt扩展库的形式提供了这种可能性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值