php - PHP密码的安全哈希和salt

  显示原文与译文双语对照的内容

目前说MD5部分不安全。 考虑到这点,我想知道使用哪种机制来保护密码。

这个问题,是"双重散列"的密码不那么安全,只需一次散列即可? 建议多次散列可能是一个好主意,而如何为单个文件实现密码保护? 建议使用 salt 。

我正在使用 PHP 。我要一个安全快速的密码加密系统。 散列密码一百万次可能更安全,但也会更慢。 如何在速度和安全性之间取得良好平衡? 另外,我希望结果具有常量的字符数。

  1. 哈希机制必须在PHP中可用
  2. 它必须是安全
  3. 它可以使用盐( 在这种情况下,所有盐都同样好)? 是否有生成好盐的方法?

另外,我是否应该在数据库( 一个使用 MD5,另一个使用 SHA,例如) 中存储两个字段? 这会使它更安全还是 unsafer?

如果我还不够清楚,我想知道使用哪种散列函数,以及如何挑选一个好的salt来保护一个安全的快速的密码保护机制。

我的问题不完全涵盖的问题:

:PHP中的SHA和MD5的区别是什么
简单密码加密
安全存储密钥的方法,asp.net的密码
如何在 Tomcat 5.5中实现咸密码

时间:

更简短,更安全的机制在所有回答- 不编写自己的密码,请使用一个也就是尝试和测试,和包含到 WordPress,Drupal等等,换句话说,openwall的phpass

大多数程序员都没有在不引入漏洞的情况下安全地编写加密相关代码的专业知识。

快速 self-test: 密码应该使用伸长,并有多少迭代是什么? 如果你不知道答案,则应使用 phpass 伸展是现在的重要特征,如密码口令机制,由于存在更快 CPU 和 gpu和 fpga 来破解密码的使用速度大致在每秒的数十亿的猜测 ( 使用 gpu ) 。

为例子,你现在可以用每 pc, 5 gpu 破解所有 8 -character Windows 密码在使用 5 6小时商品桌面 pcs. 这是 brute-forcing 换句话说,枚举并检查每个 8 -character Windows 密码,包括特殊字符,并且不是字典攻击。 在普通 CPU 上运行的彩虹表攻击也非常多,而且速度很快。 所有这一切都因为 Windows 仍然 不盐或者拉伸它的密码- 不要让同样的错误作为微软的做法 !

请参见阅读这些优秀的答案为更多关于为什么 phpass 是最佳的前进方式。

我想指出的是,PHP 5.5包含一个密码散列 API,它提供了一个围绕 crypt()的包装器。 这个API大大简化了散列,验证和重新散列密码哈希的任务。 作者还发布了一个兼容包 ( 以单一 password.php 文件的形式,你只需使用),对于那些使用了 PHP 5.3.7和更高版本的用户,现在想要使用它。

它现在只支持 BCRYPT,但它的目标是易于扩展,包括其他密码散列技术,因为技术和成本将不会使你的散列技术和成本成为散列的一部分。 如果你不明确定义自己的"安全",它也会处理生成 salt 。

API公开了四个函数:

  • password_get_info() - 返回有关给定哈希的信息
  • password_hash() - 创建密码哈希
  • password_needs_rehash() - 检查给定的哈希是否与给定的选项匹配。 检查哈希是否符合你当前的技术/成本方案,允许你在必要时重新散列
  • password_verify() - 验证密码是否与哈希匹配

只需要很少的( 找不到工作对于you,此刻这些函数接受PASSWORD_BCRYPT并PASSWORD_DEFAULT密码在那个时刻,那个常数除外,它们彼此相似的差异在于 PASSWORD_DEFAULT"在更新的更强的哈希算法支持时,可能会在新的PHP发行版中更改。"上使用PASSWORD_DEFAULT和 password_needs_rehash() 登录( 必要时再进行再散列) 应该确保你的散列值是合情合理的弹性来brute-force会导致这种

编辑:我刚刚意识到这是在罗伯特的回答中简单提到的。 我将在这里留下这个答案,因为我认为它提供了更多关于它如何工作的信息,以及它为那些不认识安全性的人提供的易用性。

我使用的是 Phpass,它是一个简单的one-file PHP类,可以在几乎每个PHP项目中实现。 参见中的H 类。

默认情况下它使用最强可用加密也就是Phpass中实现,然后是 bcrypt 和寻求其他的算法软件加密传递给MD5提供向后兼容性,以Wordpress框架( 如。

返回的哈希可以存储在数据库中,因为它是。 生成哈希的示例如下:


$t_hasher = new PasswordHash(8, FALSE);
$hash = $t_hasher->HashPassword($password);

要验证密码,可以使用:


$t_hasher = new PasswordHash(8, FALSE);
$check = $t_hasher->CheckPassword($password, $hash);

要记住事项

很多关于PHP密码加密的说法,大多数都是非常好的建议,但在开始使用PHP进行密码加密之前,请确保你已经实现了以下实现或者准备好实现。

服务器

端口

不管你的加密是多么好,如果你没有适当地保护运行PHP和数据库的服务器,你的工作就毫无价值。 大多数服务器的功能都是相同的,它们有分配的端口,允许你通过ftp或者shell远程访问它们。 请确定你更改了已经激活的远程连接的默认端口。 通过不这样做,你已经使攻击者在访问你的系统时做了一个更少的步骤。

用户名

对于世界上最好的东西,不要使用用户名 admin,根或者类似的东西。 此外,如果你在基于unix的系统上不让根帐户登录,它应该总是为 sudo 。

密码

你告诉你的用户用好的密码来避免被黑客攻击。 当你打开后门的时候,把你的前门锁起来是什么意思。

数据库

服务器

理想情况下,你希望将数据库和应用程序放在单独的服务器上。 有时这种情况无法实现成本极低,但它能支持一些安全等问题那么攻击者得通过两个步骤来完全访问系统。

用户

始终让应用程序有自己的帐户访问数据库,并且只授予它需要的特权。

然后有一个单独的用户帐户,它没有存储在服务器上的任何地方,甚至在应用程序中。

像永远不要做根或者类似的东西。

密码

遵循与所有好密码相同的准则。 同样不要在同一系统上的任何服务器或者数据库帐户上重用相同的密码。

磅的PHP

密码

不要在数据库中存储密码,而是存储哈希和唯一 salt,我将解释后面的解释。

HASHING

单向散列算法,决不哈希密码在某种程度上,它可以被一直倒退。哈希表应该是一种方法,这意味着你不反转它们以相同的方式和密码,则做比较而不是哈希所输入的密码,然后比较这两个哈希值。 这意味着即使攻击者访问数据库,他也不知道真正的密码是什么,只是它得到的散列。 这意味着在最糟糕的情况下为你的用户提供更多的安全性。

这里有很多好的哈希函数,但是你需要选择一个好的算法来使哈希生效。 ( bcrypt和类似的算法是不错的算法。)

当散列速度是关键时,越是抵抗暴力攻击的速度越慢。

哈希中最常见的错误之一是哈希对用户来说不是唯一的。 这主要是因为盐不是唯一生成的。

腌渍

密码在哈希前应该一直被腌制。 将随机字符串添加到密码中,这样类似的密码在数据库中不会出现相同的情况。 但是如果salt对每个用户都不是唯一的( IE: 你用的是硬编码的盐,比你的盐不值钱。 因为一旦攻击者计算出一个密码 salt,他就拥有了所有的salt 。

当你创建salt时,确保它对你正在使用的密码是唯一的,然后在你的数据库中存储已经完成的散列和 salt 。 这样做的目的是使攻击者在获得访问权之前,不得不逐个地破解每个salt和散列。 这意味着攻击者的工作和时间更多。

用户创建密码

如果用户正在通过前端创建密码,这意味着必须将它的发送到服务器。 这将打开一个安全问题,因为这意味着未加密的密码将被发送到服务器,如果攻击者能够监听并访问所有你在PHP中的安全。 总是安全地传输数据,这是通过SSL实现的,但是即使是SSL也不是( openssl缺陷是一个例子)的完美 Heartbleed 。

同时让用户创建一个安全的密码,它很简单,应该总是做的,用户会很感激的。

最后,不管你采取什么安全措施都是 100%安全的,更先进的保护技术变得更先进。 但遵循这些步骤将使你的站点更加安全,并使攻击者不希望在。

下面是一个为密码创建哈希和salt的PHP类

http://git.io/mSJqpw

在 PHP 5.5中,PHP有简单的安全函数用于散列和验证密码,password_hash()password_verify()


$password = 'anna';
$hash = password_hash($password, PASSWORD_DEFAULT);
$expensiveHash = password_hash($password, PASSWORD_DEFAULT, array('cost' => 20));

password_verify('anna', $hash);//Returns true
password_verify('anna', $expensiveHash);//Also returns true
password_verify('elsa', $hash);//Returns false

当使用 password_hash() 时,它会生成一个随机salt并将它的包含在输出的哈希( 随着成本和算法的使用。) password_verify() 中,然后读取哈希并确定salt和加密方法使用,并根据提供的明文密码验证它。

提供 PASSWORD_DEFAULT 指示PHP使用已经安装版本的PHP的默认哈希算法。 确切地说,哪种算法是打算在未来版本中随时间变化,所以它将永远是最强大的可用算法之一。

增加成本( 默认为 10 ) 使得散列更加困难,但也意味着生成散列和验证密码对你的服务器的CPU更有效。

位于哈希和 password_verify() 拿起对it,注意,即使默认的使用可能会改变,旧的哈希值将继续验证得很好,因为算法消息摘要算法是 stored.

...