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

这个问题,“双重哈希”密码是否比只哈希一次更不安全? 建议哈希多次可能是一个好主意,而如何实现个别文件的密码保护?建议使用盐。

我用的是PHP。我想要一个安全快捷的密码加密系统。对一个密码进行一百万次哈希运算可能更安全,但也更慢。如何在速度和安全之间取得良好的平衡?此外,我更希望结果具有恒定数量的字符。

哈希机制必须在PHP中可用 必须是安全的 它可以使用盐(在这种情况下,所有的盐都一样好吗?有没有办法生产出好的盐?)

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

以防我不够清楚,我想知道要使用哪个哈希函数,以及如何选择一个好的盐,以便拥有一个安全和快速的密码保护机制。

没有完全涵盖我的问题的相关问题:

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


当前回答

需要记住的事情

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

服务器

港口

无论您的加密技术有多好,如果您不能正确地保护运行PHP和DB的服务器,那么您所有的努力都是徒劳的。大多数服务器的功能相对相同,它们都有指定的端口,允许您通过ftp或shell远程访问它们。确保您更改了活动的任何远程连接的默认端口。如果不这样做,实际上就使攻击者在访问您的系统时少做了一步。

用户名

在这个世界上,最好不要使用admin、root或类似的用户名。此外,如果你是在一个基于unix的系统上,不要让根帐户登录可访问,它应该总是只有sudo。

密码

你告诉你的用户要设置好的密码以避免被黑客攻击,你也要这么做。当后门大开着的时候,费劲地锁上前门又有什么意义呢?

数据库

服务器

理想情况下,您希望DB和APPLICATION位于不同的服务器上。由于成本原因,这并不总是可行的,但它确实具有一定的安全性,因为攻击者必须通过两个步骤才能完全访问系统。

USER

始终让您的应用程序拥有自己的帐户来访问DB,并且只给它所需的特权。

然后为您创建一个单独的用户帐户,该帐户不存储在服务器上的任何地方,甚至不存储在应用程序中。

比如总是不要做这个根或类似的东西。

密码

遵循与所有好密码相同的原则。另外,不要在同一系统上的任何SERVER或DB帐户上重复使用相同的密码。

PHP

密码

永远不要在你的数据库中存储密码,而是存储哈希和唯一的盐,我将在后面解释为什么。

哈希

单向哈希!!!!!!!永远不要以一种可以反转的方式哈希密码,哈希值应该是一种方式,这意味着你不反转它们并将它们与密码进行比较,而是以同样的方式哈希输入的密码并比较两个哈希值。这意味着即使攻击者访问了数据库,他也不知道实际的密码是什么,只知道其结果哈希值。这意味着在最糟糕的情况下为用户提供更多的安全性。

有很多不错的散列函数(password_hash, hash等等),但是为了使散列有效,您需要选择一个好的算法。(bcrypt和类似的算法都是不错的算法。)

当哈希速度是关键时,越慢越能抵抗暴力攻击。

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

在散列之前,密码应该始终加盐。Salting在密码中添加一个随机字符串,这样类似的密码在DB中就不会出现相同的密码。然而,如果盐对每个用户都不是唯一的(例如:你使用了硬编码的盐),那么你几乎已经让你的盐变得毫无价值。因为一旦攻击者找到了一个密码盐,他就有了所有密码盐。

当你创建一个salt时,确保它是唯一的密码,然后将完成的散列和salt存储在你的DB中。这将使攻击者在获得访问权限之前必须单独破解每个盐和哈希。这对攻击者来说意味着更多的工作和时间。

用户创建密码

如果用户通过前端创建密码,则意味着必须将密码发送到服务器。这就产生了一个安全问题,因为这意味着未加密的密码将被发送到服务器,如果攻击者能够监听和访问,那么PHP中的所有安全性都是毫无价值的。始终安全地传输数据,这是通过SSL完成的,但即使SSL也不是完美无缺的(OpenSSL的Heartbleed缺陷就是一个例子)。

还要让用户创建一个安全的密码,这很简单,应该一直这样做,用户最终会感激它。

最后,无论你采取什么安全措施,没有什么是100%安全的,保护的技术越先进,攻击就会变得越先进。但是,遵循这些步骤将使您的站点更加安全,并且攻击者更不愿意进行攻击。

下面是一个PHP类,它可以轻松地为密码创建散列和盐

http://git.io/mSJqpw

其他回答

谷歌表示SHA256对PHP可用。

你一定要加盐。我建议使用随机字节(不要限制自己使用字符和数字)。通常情况下,你选择的时间越长,就越安全、越慢。64字节应该就可以了。

我不会以两种不同的方式存储哈希密码,因为这样的话,系统至少和正在使用的最弱的哈希算法一样弱。

从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()时,它生成一个随机的盐并将其包含在输出的哈希中(以及使用的代价和算法)。password_verify()然后读取该哈希并确定使用的盐和加密方法,并根据提供的明文密码验证它。

提供PASSWORD_DEFAULT指示PHP使用已安装的PHP版本的默认哈希算法。具体哪种算法在未来的版本中会随着时间的推移而改变,因此它将始终是可用的最强算法之一。

不断增加的成本(默认为10)使得哈希更难使用暴力,但也意味着生成哈希并根据它们验证密码将为服务器的CPU带来更多的工作。

请注意,即使默认的哈希算法可能会改变,旧的哈希将继续进行验证,因为所使用的算法存储在哈希中,password_verify()会捕获它。

我只想指出,PHP 5.5包含一个密码哈希API,它提供了crypt()的包装器。这个API极大地简化了哈希、验证和重哈希密码哈希的任务。作者还发布了一个兼容性包(以您只需要使用的单个password.php文件的形式),供那些使用PHP 5.3.7及以后版本并希望立即使用它的用户使用。

它目前只支持BCRYPT,但它的目标是轻松扩展到包括其他密码哈希技术,因为技术和成本存储为哈希的一部分,对您首选的哈希技术/成本的更改不会使当前哈希失效,框架将自动地在验证时使用正确的技术/成本。如果您没有显式地定义自己的盐,它还可以处理生成“安全”盐。

API公开了四个函数:

Password_get_info() -返回关于给定散列的信息 Password_hash()—创建密码散列 Password_needs_rehash()—检查给定的散列是否与给定的选项匹配。有用的检查散列是否符合您当前的技术/成本方案,允许您在必要时重新散列 Password_verify()—验证密码是否与散列匹配

目前,这些函数接受PASSWORD_BCRYPT和PASSWORD_DEFAULT密码常量,它们目前是同义词,区别在于PASSWORD_DEFAULT“在支持更新、更强的散列算法的新PHP版本中可能会改变”。在登录时使用PASSWORD_DEFAULT和password_needs_rehash()(并在必要时重新进行散列)应该确保您的散列对暴力攻击具有合理的弹性,几乎不需要做任何工作。

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

我使用的是Phpass,这是一个简单的单文件PHP类,可以在几乎每个PHP项目中非常容易地实现。参见The 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);