PHP中常见密码处理方法及建议总结
前言
在使用PHP开发Web应用的过程中,很多应用都需要用户注册,而在注册的时候,我们需要处理用户的信息,最常见的就是邮箱和密码。本文旨在讨论密码处理:即密码的加密。
我们不需要强调密码安全的重要性。随着网络攻击的增加,如果我们不妥善处理密码或采取防御措施,我们的应用程序肯定会受到来自各方面的威胁和攻击。
因此,作为开发者,我们需要对用户的密码采取防范措施。
关于密码我们应该遵守的一些原则
永远不知道用户的密码
我们绝不能知道用户的密码,也不能有办法获取用户的密码。我们知道的越少(包括我们的开发人员本身),我们就越安全。永远不要限制用户的密码
最好不要限制密码的长度和格式。如果要求密码符合特定的模式,其实也是为那些没有良苦用心的人提供了一种攻击方式。如果需要约束,建议只限制最小长度。将常用密码或基于字典创建的密码添加到黑名单中也是一个好主意。不要通过电子邮件发送用户密码
对于web应用程序,在重置或修改密码时,我们应该在邮件中发送用于设置或修改密码的URL。并且这个URL应该包含一个唯一的令牌,在设置或修改密码时只能使用一次。设置或修改密码后,我们应该将此令牌设置为无效。
使用bcrypt计算用户密码的哈希值
目前,通过大量的评论,最安全的哈希算法是bcrypt。
首先,我们定义两个概念,哈希和加密。哈希和加密有什么区别?
加密
加密是双向算法,加密数据可以通过解密得到。
混杂
哈希是一种单向算法,哈希后的数据无法再恢复到原始值。
哈希算法的目的,
验证数据的完整性(需要快速算法)
用户提高了密码和其他需要单向身份验证的数据的安全性(要求高安全性,甚至故意要求慢时间)。通常,我们保存在数据库中的应该是计算出的密码的哈希值。所以即使我们的数据库被泄露,他们也只能看到这些毫无意义的密码的哈希值。有许多散列算法,
讯息摘要5
MD5是消息摘要算法5,用于确保完整一致的信息传输。它是计算机中广泛使用的哈希算法之一(抽象翻译算法、哈希算法),MD5在主流编程语言中得到了广泛实现。将数据(如汉字)计算成另一个固定长度的值是哈希算法的基本原理。MD5的前身是MD2、MD3、MD4。
SHA1
安全哈希算法主要应用于数字签名标准DSS中定义的数字签名算法DSA。对于长度小于2个64位的消息,SHA1将生成一个160位的消息摘要。收到消息时,该消息摘要可用于验证数据的完整性。在传输过程中,数据很可能会发生变化,所以此时会产生不同的消息摘要。SHA1具有以下特点:信息无法从消息摘要中恢复;两个不同的消息不会产生相同的消息摘要(但是,相同的消息摘要会有1 10 48的概率,这在使用中通常被忽略)。
哈希
Bcrypt是专门为密码存储设计的算法,基于Blowfish加密算法。该书于1999年在USENIX由尼尔斯普罗沃斯和大卫马齐尔出版。bcrypt最大的优点是有一个功因子,可以用来调整计算强度,功因子包含在输出汇总中。随着攻击者计算能力的提高,用户可以在不影响现有用户登录的情况下,逐步增加工作因子。经过许多安全专家的仔细分析,bcrypt被用于以安全性著称的OpenBSD。一般认为,BCrypt比PBKDF2更能承担计算能力提升带来的风险。Bcrypt还具有广泛的函数库支持,因此我们建议使用这种方法来存储密码。
显卡矿机算力及挖矿软件对比表
Scrypt不仅计算时间长,而且占用大量内存,使得并行计算多个摘要极其困难,因此使用彩虹表进行暴力攻击更加困难。Scrypt在生产环境中应用不广泛,缺乏细致的检查和广泛的函数库支持。但是,只要scrypt在算法层面没有瑕疵,其安全性就应该高于PBKDF2和bcrypt。
目前,通过大量的评论,最安全的哈希算法是bcrypt。与MD5和SHA1不同,bcrypt算法自动添加盐来防止潜在的彩虹表攻击。Bcrypt算法将花费大量时间重复处理数据以生成安全哈希值。在这个过程中,处理数据的次数称为工作因素。工作因子的值越高,破解密码哈希的时间将呈指数级增长。
Bcrypt算法永远不会过时。如果计算机的计算速度变快,我们只需要提高工作系数。
顺带一提,在任何情况下,尽量不要使用md5算法,但至少要使用SHA系列哈希算法。因为md5算法就目前计算机的计算能力来说是比较简单的,而md5的性能优势现在完全可以忽略不计。
密码哈希应用编程接口
我们说过bcrypt算法是最安全和最适合散列我们的密码。PHP提供了一个原生的密码哈希API供我们在PHP5.5.0版本中使用,这个密码哈希API默认使用的是bcrypt哈希算法,大大简化了我们计算密码哈希值和验证密码的操作。
PHP原生密码哈希API
密码散列函数:
Password_get_info返回有关指定哈希值的信息password_hash创建密码哈希password _ needs _ rehash检查给定哈希是否与给定选项password_verify匹配验证密码是否与哈希password_get_info匹配
解释
数组密码_get_info(字符串$hash)
参数
Hash,由password_hash()创建的哈希值。
例如,
?phpvar _ dump(password _ get _ info($ hash));//example array(3){[' algo ']=int(1)[' algo name ']=string(6)' bcrypt '[' options ']=array(1){[' cost ']=int(10)} }?密码哈希
解释
string password _ hash(string $ password,integer $algo [,array $options ])
Password_hash()使用具有足够强度的单向哈希算法来创建密码哈希。Password_hash()与crypt()兼容。因此,crypt()创建的密码哈希也可以用于password_hash()。
当前支持的算法:
PASSWORD_DEFAULT使用bcrypt算法(PHP 5.5.0 default)。请注意,这个常数会随着PHP添加更新更强的算法而改变。因此,使用该常数生成的结果的长度在将来会发生变化。因此,数据库中存储结果的列可以超过60个字符(最好是255个字符)。PASSWORD_BCRYPT使用CRYPT_BLOWFISH算法创建一个哈希。这将生成一个与使用“$2y$”兼容的crypt()。结果将是一个60个字符的字符串,或者在失败时返回FALSE。支持的选项:
Salt-手动提供哈希密码的salt。这将避免自动生成盐。如果省略该值,password_hash()会自动为每个密码哈希生成一个随机的salt值。这次行动是经过深思熟虑的。自PHP 7.0.0以来,警告盐选项已被弃用。现在最好简单地使用默认的盐值。成本-表示算法使用的成本。crypt()页面上有一些成本值的示例。省略时,默认值为10。这个成本是一个很好的底线,但也许可以根据你自己的硬件增加。参数
密码,用户的密码。使用PASSWORD_BCRYPT作为算法会使密码参数最长为72个字符,超过就会被截断。Algo,一个加密算法常数,用于表示散列密码时的算法。选项,一个包含选项的关联数组。目前支持两个选项:salt,即散列密码时添加的salt(干扰字符串),以及cost,用于指示算法的递归级别。这两个值的示例可以在crypt()页面上找到。如果省略,将使用随机盐值和默认成本。例子
示例1,使用默认算法的哈希密码
?Php/** *我们想使用默认算法来散列密码*它目前是BCRYPT,将产生60个字符的结果。* *请注意,默认算法可能会随时间变化,*因此所需的存储空间可以超过60个字(255个字就好)*/echo password _ hash(' Rasmusserdorf ',password _ default)。\ n ';//输出类似于://$ 2y $10 $。VGA 1o 9 wmrjrwavxd 98 hnogsnpdzlqm 3 jq 7 kned 1 r vag v3 fykk1a示例2,手动设置成本
?Php/** *在这种情况下,我们将BCRYPT的成本增加到12。*请注意,我们已经切换到并将始终生成60个字符。*/$options=[ 'cost'=12,];echo PASSWORD _ hash(' rasmuslerdorf ',PASSWORD_BCRYPT,$options)。\ n ';//输出类似于://$ 2y $ 12 $ qjsh 496 pct 5 cebzjd/vtveh 03 fhfy 36 d4j 0lt P3 lrtee 9 hdxy3k示例3,如何选择适合当前服务器的成本
?这个php/** *的例子对服务器进行了基准测试,并检测了服务器可以承受的成本有多高。设置最高值* 8-10而不明显减慢服务器速度是一个很好的底线。如果服务器足够快,越高越好。*以下代码的目标为 50毫秒,*适合系统处理交互登录。*/$ TiME target=0.05;//50毫秒)$ cost=8;do { $ cost$ start=micro time(true);password_hash('test ',PASSWORD_BCRYPT,[' cost '=$ cost]);$ end=micro time(true);} while(($ end-$ start)$ time target);回应“找到合适的成本:”。成本。\ n ';输出类似于:
合适的成本基础: 10
password_needs_rehash
解释
boolean password _ needs _ rehash(string $ hash,integer $algo [,array $options ])
参数
Hash,由password_hash()创建的哈希值。Algo,一个加密算法常数,用于表示散列密码时的算法。选项,一个包含选项的关联数组。目前支持两个选项:salt,即散列密码时添加的salt(干扰字符串),以及cost,用于指示算法的递归级别。这两个值的示例可以在crypt()页面上找到。例如,
?php $ password=' rasmuslerdorf$ hash=' $ 2y $ 10 $ ycfsg6 elyca 568 hbi2pz 0.3 ldl5 wjgxct1n 8w/OLr/jhsiqwcqts ';//成本参数可以随着硬件的提高而不断提高。$ options=array(' cost '=11);//使用纯文本密码验证存储的哈希if (password _ verify ($ password,$ hash)){//如果(password _ needs _ rehash ($ hash,password _ default,$options)) {//如果是,请创建一个新的哈希值并替换旧的哈希值$ new hash=password _ hash($ password,password _ default,$ options);}//用户登录验证完成/.}?密码验证
解释
布尔密码验证(字符串$password,字符串$hash)
请注意,password_hash()返回的哈希包含算法、成本和盐值。因此,所有必需的信息都包括在内。使得验证功能可以验证散列,而不存储诸如盐值的附加信息。
参数
密码,用户的密码。Hash,由password_hash()创建的哈希值。例如,
?Php//如果想知道以下字符的来源,请参考password _ hash():$ hash=' $ 2y $ 07 $ bcrypt需要22 chrcte/vlqh 0 pijtjxl . 0t 1x ka8 pw 9 dmxtpoq ';if(Password _ verify(' rasmuslerdorf ',$hash)) { echo 'Password有效!';} else { echo '无效密码';}?上述例行输出:
密码有效!
PHP5.50之前的密码哈希API
Anthony Ferrara(PHP原生密码哈希API的开发人员)还为PHP5.5.0以下的PHP版本提供了irmaxell/password-compat组件(https://packagist.org/packages/ircmaxell/password-compat)
这个组件还实现了PHP密码哈希API中的所有功能,
password _ get _ info password _ hashpassword _ needs _ rehash password _ verify我们可以直接使用Composer将这个组件添加到我们的应用程序中。例如,
composer需要ircmaxell/password-compat
摘要
以上就是本文的全部内容。希望本文的内容对大家的学习或工作有一定的参考价值。有问题可以留言交流。谢谢你的支持。
版权声明:PHP中常见密码处理方法及建议总结是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。