PHP密码的安全性 - IDC资讯网_站长学院 - Java PHP Flex Python Ajax CSS 编程 开源 学习 总结 分享

PHP密码的安全性

[ 2008-04-14 09:06 | by 草山湖 ]
    如果你建了个需要用户注册的网站,那么你就有责任保证用户登陆密码的安全。如果把他们的密码用明码存放,那你就失职了。你会觉得用明码存放密码,像Reddit网站一样,可以让用户用得更方便。就算我同意你的看法,但如果你的数据库像Reddit网站一样被偷了呢?那时损失的不单是你自己的网站,因为用户通常在多个网站都用同一个登陆密码,这样,那些网站也跟着倒霉了。

    任何数据都不是绝对安全的,想想任何人都可以接触你的服务器(是不是有公司替你管理服务器?),接触你的数据库(是不是有公司替你备份数据?),但你对此却无能为力。也就是说你的数据库被偷的机会是很大的。那么,最简单的(安全措施)就是对用户的登陆密码加密。

哈希方法(Hashing)

Hash是将原密码运用单向算法运算后得出的字符串。换句话说,就是加密很容易,解密极困难(如果应用得法,解密几乎不可能)。 先将加密结果(Hash)放在数据库里,当用户登录时,可将其登录密码加密(Hash)后,再与之前放在数据库中的结果比对。如下例


if( $user->passwordhash == sha1( $_POST['password'] ) )
//(shal : Secure Hash Algorithm .译者注)
 


PHP有好几种加密算法,md5 和sha1 是用的最多的。但两者都没有人们想象的那么安全。应该用更安全的算法,安装加密引擎(PHP 5.1.2以上已内置) 后可有更多算法可用。以下是更棒的例子


if( $user->passwordhash == hash( 'whirlpool', $_POST['password'] ) )
//彩虹表 (Rainbow tables)
 


但还有个问题,偷窃者偷取数据库后,就有大量的时间使用彩虹表来破解。其原理是将常用词(比如从字典中提取每个词)加密后的字符串比对数据库里的字符串。
用不了个把小时,近半的密码可能已被破解。

防范措施就是在每个密码加密时增加一段随机产生的字符(可叫其变形算法或随便什么)。耗时的彩虹表攻击法是基於字典的词。要破解加料后的密码,就要根据增加的每一个字符重建一本字典,攻击会因太耗时而不能成事。每个密码都要附加一段不同的字符,字符本身就根本不用加密。

例子

安全加密方法如下

// get a new salt - 8 hexadecimal characters long
// current PHP installations should not exceed 8 characters
// on dechex( mt_rand() )
// but we future proof it anyway with substr()
function getPasswordSalt()
{
    return substr( str_pad( dechex( mt_rand() ), 8, '0',STR_PAD_LEFT ), -8 );
}


// calculate the hash from a salt and a password
function getPasswordHash( $salt, $password )
{
    return $salt . ( hash( 'whirlpool', $salt . $password ) );
}

// compare a password to a hash

function comparePassword( $password, $hash )
{
    $salt = substr( $hash, 0, 8 );
    return $hash == getPasswordHash( $salt, $password );
}
// get a new hash for a password
$hash = getPasswordHash( getPasswordSalt(), $password );
 

加料字符用不着加密,你可将其分存在数据库中,但我个人喜欢把其连成一串。同样的,加料字符用不着变成十六进制,但我喜欢用和哈希字符串一样的十六进制的格式。

最后,正如Thomas Ptacek说的,你没必要用世界上最快的算法来加密,它是留给攻击者用的。
编程语言 | 评论(0) | 引用(0) | 阅读(3776)