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

Posted

技术标签:

【中文标题】PHP最强的单向加密/散列方法[重复]【英文标题】:PHP Strongest one way encryption/hashing method [duplicate] 【发布时间】:2013-04-14 13:46:56 【问题描述】:

我有一个人们可以注册的网站,我需要加密他们的密码。我已经对其进行了研究,但找不到任何不会被现代 GPU 的强大功能击败的方法。

所以我来到 *** 的好心人那里问,什么是最强大的加密方法,我已尽我所能阻止人们接触数据库,但我想尽可能确定他们的如果数据库以某种方式被盗,数据会很好。

我想知道的其他事情是,以某种方式随机化密码中的字符会更安全吗?

编辑: 我使用了 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);

如果有人发现它有任何问题或任何弱点,请告诉我。

【问题讨论】:

我使用 sha1 512 ,我认为这是最好的加密方式 “最强”的是非标准的。这就是为什么许多人会在他们的加密中加入盐。 md5($salt.md5($password)) 之类的东西 - 这使得彩虹表无法使用。 我很好奇:您认为 PHP 提供的当前哪些加密不安全? 我会推荐 bcrypt php.net/manual/en/function.crypt.php,使用这个库 github.com/ircmaxell/password_compat 至于你的最后一段,永远不要推出你自己的加密货币。您自己编写的蹩脚排列密码总是比真正的散列函数弱。 【参考方案1】:

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/

希望对您有所帮助。

【讨论】:

【参考方案2】:

对于密码,您无法击败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,就可以击败它,而且由于要在本世纪内破解密码,需要大约 40 亿个 GPU,他可能也会获得不错的数量折扣。但我不会担心。

至于密码的“随机化”,没有任何意义。如果有人使用暴力破解您的密码,他将有相同的概率找到随机序列或非随机序列。如果使用 字典攻击 可能会有所帮助(即,不要尝试从 AAAAA 到 ZZZZZ 的所有内容,而是尝试 ABRAHAM、ACCORDION ……直到 ZYGOTE)。但即便如此,对服务器的攻击也不会改变任何事情(服务器会收到非随机密码!),对存储的哈希的攻击最好通过 salting 来消除,bcrypt 自动确实:即,存储$76XJ:MICKEYMOUSE 的哈希而不是MICKEYMOUSE 的哈希,以及处理输入时额外的'$76XJ:' 所需的开销。虽然必须修复随机化,但“$76X.J:”序列在每次写入时都完全不同——祝你好运搞清楚

腌制

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

user    password
alice   d9c06f88:6c14d6d313d7cbcb132b5c63650682c4

然后,在 Alice(“mickeymouse”)收到密码后,您将在数据库中查看是否存在名为 alice 的用户。如果是,请恢复盐(此处为 d9c06f88)和哈希。如果没有,设置一个“BAD”标志并获取一个固定的盐和哈希(例如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;

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

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

通过非信息实现安全

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

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

在用户的情况下,连名字比较都会

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

因此,从 HTTP(s) 连接的另一端说出发生了什么并不容易。

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

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

这样的密码是有时间的

提高服务器安全性以防止暴力破解的一种便捷方法是在密码身份验证上实施延迟,并且可能(如果您真的很偏执)在几次错误尝试后进行验证码锁定。

您不希望第一次尝试验证码,因为用户对验证码的看法很模糊。

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

在某些情况下,这可能会在不知不觉中发生。似乎有些白痴在使用我的银行,每隔几个月我就会收到一条短信,上面写着“在您的家庭银行系统中输入了错误的 PIN”。然后我必须从我的手机登录,以重置不成功尝试计数器;因为如果白痴没有意识到他无法进入他的帐户,因为他输入了我的帐号,三遍,它是我的 em> 帐户被锁定,我必须亲自去银行请求他们重置我的访问权限。让我告诉你,这是下层地区的主要痛苦,即使知道这不是他们的错,我仍然怨恨我的银行。你不想让你的用户产生这样的感觉。

最好把负担转移到客户身上:

(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

【讨论】:

我对随机化的看法是,即使他们确实设法将密码恢复为纯文本,这也不是他们在其他网站上用于其他帐户的实际密码。 另外我想问一下盐腌是怎么工作的?我是否只是生成一个随机字符串,然后在加密时将其添加到密码中,并将其添加到数据库中以供以后检查。 哦,通过散列,您无法将密码恢复为纯文本。这就是“一种方式”的含义...有关密码的信息丢失并且无法恢复,因为它不再存在。 @user1763295 - salt 确实会与哈希值一起存储在数据库中。大多数 BCrypt 实现会自动为每个密码生成一个唯一的盐,并将其以明文形式包含在生成的哈希值中。随机化将为您的哈希值添加一个秘密,这在某些情况下可能是一个优势。但是,添加 pepper 可以更轻松地获得相同的优势。如果您有兴趣阅读有关该主题的更多信息,我邀请您阅读我的tutorial about secure password storing。

以上是关于PHP最强的单向加密/散列方法[重复]的主要内容,如果未能解决你的问题,请参考以下文章

单向散列算法的常见算法

一文搞懂单向散列加密:MD5SHA-1SHA-2SHA-3

一文搞懂单向散列加密:MD5SHA-1SHA-2SHA-3

数字签名数字证书对称加密算法非对称加密算法单向加密(散列算法)

数字签名数字证书对称加密算法非对称加密算法单向加密(散列算法)

使用单向散列技术(SHA1)加密数据库的密码