PHP最强单向加密/散列方法[重复]

问题描述 投票:4回答:2

这个问题在这里已有答案:

我有一个人们可以注册的网站,我需要加密他们的密码。我研究了它,但我发现任何方法都不会受到现代GPU的强大影响。

所以我来向StackOverflow的优秀人士询问,最强大的加密方法是什么,我已尽力阻止人们掌握数据库,但我希望尽可能确保他们的数据是如果数据库以某种方式被盗,那很好。

我想知道的其他事情是,以某种方式随机化密码中的字符会更安全,但是你可以将它们再次随机化以便登录吗?

编辑:我使用了Andrew Moore(How do you use bcrypt for hashing passwords in PHP?)的bcrypt实现并提出了这个:

public static function Encrypt($Str,$Salt)
{
    $bcrypt = new \bcrypt();
    return $bcrypt->hash(SERVER_SALT . md5($Str) . $Salt);
}

如果有人发现任何错误或任何弱点,请告诉我。

php passwords password-hash
2个回答
17
投票

对于密码,你无法击败bcrypt。这是SO上的链接:How do you use bcrypt for hashing passwords in PHP?。它的主要优点是:它本身就很慢(以及安全)。虽然普通用户将使用它一次,并且不会欣赏十分之一到百万分之一秒之间的差异,但是一个破解者会发现他不需要在四天内找到密码,而是需要十二个世纪(除了强迫Blowfish之外)每秒一百万次尝试不需要四天:除了实施错误和无法预见的加密突破,the heat death of the Universe will still come first)。

对于数据,我依赖于数据库引擎本身; MySQL支持AES,这非常好。是的,有足够的GPU可以击败它,并且由于在本世纪内破解代码需要大约四十亿,他可能也会得到很好的数量折扣。但我不担心。

至于密码的“随机化”,它没有用处。如果有人要求强制使用您的密码,他将有相同的概率找到随机序列或非随机序列。如果一个人使用字典攻击(即,不尝试从AAAAA到ZZZZZ的所有东西,但尝试ABRAHAM,ACCORDION,......,比如说,ZYGOTE)可能会有所帮助。但即便如此,对服务器的攻击也不会改变任何东西(服务器收到非随机密码!),对存储的哈希的攻击将更好地通过salting无效,bcrypt会自动执行:即存储$ 76的哈希值XJ:MICKEYMOUSE而不是MICKEYMOUSE的哈希值,以及在输入时处理额外'$ 76XJ:'所需的开销。虽然随机化必须得到修复,但“$ 76X.J:”序列在每次写入时都完全不同 - 祝你好运!

如果您自己实施salting(如上所示,使用bcrypt,您不需要),您可以通过生成唯一的随机序列并将其存储在密码字段或第二个字段中来实现。例如

user    password
alice   d9c06f88:6c14d6d313d7cbcb132b5c63650682c4

然后,在收到Alice(“mickeymouse”)的密码后,您将查看数据库以查看是否存在名为alice的用户。如果是的话,恢复盐(这里是d9c06f88)和哈希。如果没有,则设置“BAD”标志并获取固定的salt和hash(例如12345678:0000000...)。

在MySQL中,这可以使用UNION完成:

SELECT password_fields FROM users WHERE user=? AND hash=?
UNION SELECT
    '12345789' as salt,
    'ffffffffffffffffffffffff' as hash,
    'fake' as user
LIMIT 1;

将在大致相同的时间内检索正确的数据或不正确的集合(这可以防止有人猜测存在哪些名称,而不是通过计时回答“错误的用户或密码”所需的时间)。

然后连接salt和密码,并生成d9c06f88:mickeymouse的哈希值。如果它不匹配,或者设置了“BAD”标志,则拒绝密码(而不是使用'bad'标志,您可以重复测试MySQL已经执行的用户匹配:您可以通过替换用户名来初始化用户名带有无效字符的最后一个字符,以确保它永远不会与真实用户匹配)。

通过非信息安全

选择固定字符串的附加扭曲是有用的,因为你想要三种情况,“用户不存在”,“用户存在但密码不正确”和“用户存在且密码正确”是相似的(相同的复杂性,相同计算费用)尽可能。

这样,攻击者就不太可能知道发生了什么:用户是不正确的?密码错了吗?等等。如果时间足够不同(例如对有效用户进行两次查询,对无效用户进行一次查询),小心,时间和好秒表的攻击者可以统计确定是否存在给定用户名。

在用户的情况下,甚至名称比较将是

 johnsmith     against   johnsmith            if johnsmith exists
 johnsmith     against   johnsmit?            if johnsmith does not exist

所以告诉从HTTP连接的另一端发生的事情并不容易。

出于同样的原因,您不会为“错误用户”和“错误密码”返回两个不同的错误,但总是“错误的用户或密码”;对于用户,可以选择接收到他/她的注册电子邮件的电子邮件以提醒他/她用户名。当然,您希望系统在发送类似电子邮件到同一用户24小时之前不发送此类电子邮件,以防止系统被利用用虚假的“恢复电子邮件”来骚扰某人。

如果您确实发送了电子邮件,您将等到预设时间到期(例如,3秒),然后通知用户如果用户名存在,那么他们应该检查他们的收件箱(以及垃圾邮件文件夹以便进行测量)。

这样的密码会有时间

提高服务器安全性以防止强制攻击的一种便捷方法是实现密码验证的延迟,并且可能(如果你真的是偏执狂)在经过一些X次错误尝试后进行了CAPTCHA锁定。

您不希望CAPTCHA首次尝试,因为用户会对CAPTCHA进行暗淡视图。

延迟锁定通常使用sleep(或等效的)实现,或使用“锁定直到由管理员手动重置”策略。两种方法都很糟糕。锁定功能可用于通过锁定用户或创建大量停止在“密码身份验证延迟”状态的服务器线程来创建拒绝服务攻击(他们不会使用CPU,但他们仍将使用内存,套接字和其他资源)。

在某些情况下,这可能会在不知不觉中发生。似乎有一些白痴使用我的银行,每隔几个月我就会收到一条短信说“你的家庭银行系统输入了错误的密码”。然后我必须从我的手机登录,重置不成功的尝试计数器;因为如果这个白痴没有意识到他因为输入了我的账号而无法进入他的账户,这三次,我的账号被锁定了,我必须去银行并请求他们重置我的账号。访问。我告诉你,这是幽冥地区的一个主要痛苦,即使知道这不是他们的错,我仍然怨恨我的银行。您不希望在用户中产生这种感受。

最好是减轻客户的负担:

(very pseudo code)
login = FAIL
if in SECURITY LOCKOUT MODE for this account
    if a session is open and contains a last-attempt time
        if at least DELAY seconds have elapsed since last-attempt
            check the password
            if it is correct
                login = OK
                zero password counter, exit lockout mode.
                # An "innocent" user enters with no lockout! Yay!
            end
        else
            # "Early knocker". Either a bruteforcing robot
            # or a too clever user in a hurry. But we can't
            # tell them apart.
        end
    else
        # No session. Either a sessionless bruteforcing robot
        # or a unaware, innocent user. Again we can't tell them
        # apart. So we bounce both.

        # But a genuine user will assume he has mistyped the password,
        # or anyway will read the warning page, and will login after ONE
        # round of delay.

        # Users with password saved in browser will just click
        # "login" again and be logged in.

        # A robot will find itself delayed and ALL ITS PASSWORDS IGNORED
        # every single time. Even if it finds the right password... it will
        # not work.
    end
else
    check the password
    if it is correct
        # Good user, first attempt, fast login.
        login = OK
    else
        # Beginning to doubt this is a good user...
        increase password counter
        if it is > MAX_ATTEMPTS
            enter SECURITY LOCKOUT MODE for this account
        end
    end
end
if login is not OK
    generate a page with HTTP_REFRESH time of DELAY+1 seconds
    and a session ID, saying "User or password unknown,
    or you tried to login before HH:MM:SS (DELAY seconds).
    The page might also contain a Javascript timer, just in
    case. The delay is 1s more than necessary as a safety
    margin.
end

0
投票

AES 256位加密非常“强大”,这意味着它是最新的加密标准之一,难以破解。我已经读过,如果你采用蛮力方法来破解它,你将需要世界上所有的计算能力。

查看:

How to do AES256 decryption in PHP?

和:

http://en.wikipedia.org/wiki/Advanced_Encryption_Standard http://www.andrew-kirkpatrick.com/2013/01/aes-encryption-with-php-256-bit-using-iv/

希望有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.