我想知道这个功能(部分取自~2岁的phpBB版本)是否足够好。

如果没有,为什么?
您将如何更改它(使现有用户无缝转换)?

hash_pwd()的结果将保存在DB中。

function hash_pwd($password)
{
    $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';

    $random_state = $this->unique_id();
    $random = '';
    $count = 6;

    if (($fh = @fopen('/dev/urandom', 'rb')))
    {
        $random = fread($fh, $count);
        fclose($fh);
    }

    if (strlen($random) < $count)
    {
        $random = '';

        for ($i = 0; $i < $count; $i += 16)
        {
            $random_state = md5($this->unique_id() . $random_state);
            $random .= pack('H*', md5($random_state));
        }
        $random = substr($random, 0, $count);
    }

    $hash = $this->_hash_crypt_private($password, $this->_hash_gensalt_private($random, $itoa64), $itoa64);

    if (strlen($hash) == 34)
    {
        return $hash;
    }

    return false;
}


function unique_id()
{
    $val = microtime();
    $val = md5($val);

    return substr($val, 4, 16);
}

function _hash_crypt_private($password, $setting, &$itoa64)
{
    $output = '*';

    // Check for correct hash
    if (substr($setting, 0, 3) != '$H$')
    {
        return $output;
    }

    $count_log2 = strpos($itoa64, $setting[3]);

    if ($count_log2 < 7 || $count_log2 > 30)
    {
        return $output;
    }

    $count = 1 << $count_log2;
    $salt = substr($setting, 4, 8);

    if (strlen($salt) != 8)
    {
        return $output;
    }

    /**
    * We're kind of forced to use MD5 here since it's the only
    * cryptographic primitive available in all versions of PHP
    * currently in use.  To implement our own low-level crypto
    * in PHP would result in much worse performance and
    * consequently in lower iteration counts and hashes that are
    * quicker to crack (by non-PHP code).
    */
    if (PHP_VERSION >= 5)
    {
        $hash = md5($salt . $password, true);
        do
        {
            $hash = md5($hash . $password, true);
        }
        while (--$count);
    }
    else
    {
        $hash = pack('H*', md5($salt . $password));
        do
        {
            $hash = pack('H*', md5($hash . $password));
        }
        while (--$count);
    }

    $output = substr($setting, 0, 12);
    $output .= $this->_hash_encode64($hash, 16, $itoa64);

    return $output;
}

function _hash_gensalt_private($input, &$itoa64, $iteration_count_log2 = 6)
{
    if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31)
    {
        $iteration_count_log2 = 8;
    }

    $output = '$H$';
    $output .= $itoa64[min($iteration_count_log2 + ((PHP_VERSION >= 5) ? 5 : 3), 30)];
    $output .= $this->_hash_encode64($input, 6, $itoa64);

    return $output;
}

function _hash_encode64($input, $count, &$itoa64)
{
    $output = '';
    $i = 0;

    do
    {
        $value = ord($input[$i++]);
        $output .= $itoa64[$value & 0x3f];

        if ($i < $count)
        {
            $value |= ord($input[$i]) << 8;
        }

        $output .= $itoa64[($value >> 6) & 0x3f];

        if ($i++ >= $count)
        {
            break;
        }

        if ($i < $count)
        {
            $value |= ord($input[$i]) << 16;
        }

        $output .= $itoa64[($value >> 12) & 0x3f];

        if ($i++ >= $count)
        {
            break;
        }

        $output .= $itoa64[($value >> 18) & 0x3f];
    }
    while ($i < $count);

    return $output;
}

===============>>#1 票数:52 已采纳

您给出的代码是PHPASS的端口,特别是“可移植”算法。 注意portable的资格。 如果您将true作为第二个构造函数参数传递,则这仅适用于phpass库。 从这里开始,在这个答案中, phpass 涉及便携式算法,而不是库本身。 如果您没有明确指定portable话,默认情况下该库将执行bcrypt ...

PHPBB团队并没有自己开发这个(非常好的东西),而是直接从phpass移植它(可论证)。

我们在这里应该问几个问题:

这不好吗?

简短的回答是不,这不错。 它提供了非常好的安全性。 如果你现在有这方面的代码,我不会急于下车。 它适用于大多数用途。 但话说回来,如果你开始一个我不会选择它的新项目,还有更好的选择。

有哪些弱点?

  • 相对于pbkdf2phpass算法使用hash() ,其中pbkdf2()使用hash_hmac() 现在, HMAC在内部为每个调用运行2个哈希,但是PHP实现只需要执行一次对hash()的单次调用(不是C很好吗?)。 所以我们从hash_hmac得到2个哈希值,62%的时候它需要hash()来执行2个哈希值。

    这意味着什么? 那么,对于一个给定的运行时间pbkdf2会跑的比增加了约37.5%的哈希phpass算法。 在给定时间内更多哈希==良好,因为它导致执行更多计算。

    所以pbkdf2是大约37.5%要强于phpass使用相同的原语(当md5在这种情况下)。 但是pbkdf2也可以采用更强的原语。 所以我们可以使用pbkdf2sha512来获得比phpass算法phpass着的优势(主要是因为sha512是一种比md5计算更多的更难的算法)。

    这意味着pbkdf2不仅能够在相同的时间内生成更多的计算,而且能够生成更难的计算。

    随着中说,差别不是显著。 这是非常可测量的, pbkdf2肯定比phpass “更强”。

  • 相对于bcrypt :这比较难以进行比较。 但让我们来看看它的表面。 phpass使用md5和PHP中的循环。 pbkdf2使用任何原语(在C中)和PHP中的循环。 bcrypt在C中使用全部自定义算法(意味着它与任何可用的哈希算法不同)。 因此,对于蝙蝠来说, bcrypt具有显着优势,因为算法全部都在C中。这允许每单位时间更多的“计算”。 从而使其成为更有效的慢速算法(在给定的运行时间内进行更多计算)。

    但同样重要的是它的计算量是计算的质量。 这可能是一篇完整的研究论文,但简而言之,它归结为这样一个事实:bcrypt在内部使用的计算比普通的哈希函数要难得多。

    bcrypt更强大的本质的一个例子是bcrypt使用比普通散列函数大得多的内部状态。 SHA512使用512位内部状态来计算1024位的块。 bcrypt使用大约32kb的内部状态来计算单个576位的块。 事实上, bcrypt的内部状态比SHA512 (以及md5phpassphpass部分地说明了bcrypt的强大性质。

应该避免

对于新项目, 绝对 这不是坏事。 事实并非如此。 这是有明显更强的算法(按数量级)。 那么为什么不使用它们呢?

有关bcrypt如何更强大的进一步证明,请查看Password13(PDF)中幻灯片,幻灯片启动了25 GPU集群以破解密码哈希值。 以下是相关结果:

  • md5($password)
    • 每秒180亿次猜测
    • 9.4小时 - 所有可能的8个字符密码
  • sha1($password)
    • 每秒61亿次猜测
    • 27小时 - 所有可能的8个字符密码
  • md5crypt (与phpass 非常相似,成本为10):
    • 每秒7700万次猜测
    • 2。5年 - 所有可能的8个字符密码
  • bcrypt ,费用为5
    • 每秒71千猜
    • 2700年 - 所有可能的8个字符密码

注意:所有可能的8个字符密码都使用94个字符集:

a-zA-Z0-9~`!@#$%^&*()_+-={}|[]\:";'<>,.?/

底线

因此,如果您正在编写新代码,毫无疑问请使用bcrypt 如果你现在有生产中的phpasspbkdf2 ,你可能想要升级,但它并不是一个明确的“你非常脆弱”。

===============>>#2 票数:19

快速回答:

使用bcrypt(当它准备好时)或来自ircmaxell的password_compat库 - 它是一个bcrypt库。

答案很长:

对于当前的技术而言,这太复杂且过时。 应该避免Md5,只是盐腌不够好。 使用bcrypt并避免头痛。

你可能会问自己为什么那个特定的库? 那么相同的功能将在PHP 5.5中提供,因此您不必更改任何编码。 祝你好运,并保持简单高效。 登录和密码的东西也很慢。

更新1

@Gumbo - >没有MD5没有被破坏,但现在和过去像MD5这样的哈希的主要目的是用于文件检查(如你所知,检查文件的内容是否可以信任而不是密码存储),因为哈希是非常的快速解密,因为你不会使用Bcrypt来检查文件的内容,因为你等待30-45秒......所以这意味着哈希特意是要快速读取。 与bcrypt相比,甚至SHA512仍然完全劣质。 这就是为什么必须在PHP中推动像Blowfish / Bcrypt这样的强密码算法。 我们作为用户和程序员都必须扩展普通密码存储或低级散列算法不是答案的知识 - 绝不应该用于这些敏感信息。

现在向OP转换到新系统,您首先会向所有用户发送通知,声明“为​​了您的安全,密码加密系统已更新........”,那么您会问他们对于一次性密码更新,一旦你进行密码更新,你将使用名为password_verify的函数,如果你想最大程度地控制你的成本比率,你可以使用password_needs_rehash,如果由于某种原因你选择更改与密码相关的成本。

这样做不会占用大量代码,因为在密码保护中你会获得的收益会影响必须“重新编码”新密码系统的负面影响。

希望这可以解答大多数问题,但是IRCmaxell的答案在不同的算法上进一步深入细节是非常优越的! 祝你好运OP,非常感谢ircmaxell!

更新2

此外,这样存储的密码是否真的可以破解? 怎么样? (我现在好奇)

任何事情都被打破了我的网络安全教授告诉我的事情......我嘲笑他。 现在我看到了他眼中的东西......好吧......这绝对是真的!

Bcrypt CURRENTLY是存储密码的最佳方法! 但是,如果你看看Scrypt似乎有希望但PHP不支持。 尽管如此,一切都被打破,只是时间问题,直到地下室的一些“极客”才会破解Bcrypt。 但是现在我们很安全..就像我们安全,IPv4永远不会耗尽......等等吗?...;)

希望这能解决你提出的问题,先生。 也只是把它放到上下文我的系统是17的成本,登录需要大约20 - 30秒,但当我向我的教授和我的客户介绍系统时,为什么它应该是强制性的,他们喜欢它和我们感到放心,他们受到了保护。

===============>>#3 票数:1

我会选择bcrypt.It很好除了加入一个盐来防止彩虹表攻击,bcrypt是一个自适应功能:随着时间的推移,迭代计数可以增加,使其更慢,所以它仍然抵抗暴力搜索攻击即使计算能力越来越强。

实现: 如何在PHP中使用bcrypt进行散列密码?

===============>>#4 票数:-5

(对不起,我的英语一开始)

几乎没有问题,所有评论者在回答之前都要问:

该代码将在何处使用?

它将保护哪种数据?

它会用于关键级系统吗?

好吧,我们有一些用例。 我使用简化的密码生成器用于IS,是的,它确实不是'第三次世界大战准备好',但是用户将密码告诉某人,或者它将被他的计算机中的某些恶意软件泄露的机会仍然大得多。

  • md5很弱,使用最新的指纹生成器(sha128,sha256,sha512)
  • 使用随机长度的盐像:

     private function generateSalt() { $salt = ''; $i = rand(20, 40); //min,max length for($length = 0; $length < $i; $length++) { $salt .= chr(rand(33, 126)); } return $salt; } 
  • 然后生成一些密码:

     private function generatePass() { $vocabulary = 'abcdefghijklmnopqrstuvwxyz0123456789'; $password = ''; $i = rand(7,10); for($length = 0; $length < $i; $length++) { $password .= substr($vocabulary,rand(0, 35),1); } return $password.'-'; // avoid copy`n`paste :) } 
  • 是密码应该更强,但用户永远不会记住它,它将保存到浏览器或写在某处。 期望和安全与现实。

     $newSalt = $this->generateSalt(); $newPass = $this->generatePass(); $newHash = hash('sha512', $newPass.':'.$newSalt); // now store hash and salt into database 
  • 有新的哈希,但它还没有结束,真正的工作已经开始:

    1. 记录
    2. 会话保护
    3. user,user + ip,ip temp / perm banning
    4. 等等

login + logout + re / generate password:1或2个SQL表和几个kb的代码

关于安全性的其他事情:许多表,实际上超过几kb的代码

  ask by koichirose translate from so

未解决问题?本站智能推荐:

16回复

“双重哈希”密码是否比仅仅哈希一次更安全?

在存储之前对密码进行两次哈希处理的安全性是否比仅仅哈希一次更安全? 我在说什么是这样做的: 而不仅仅是这个: 如果它不太安全,你能提供一个很好的解释(或链接到一个)吗? 此外,使用的哈希函数是否有所作为? 如果混合使用md5和sha1(例如)而不是重复相同的散列函数
3回复

如何使用Taylor Hornby的密码哈希函数

我一直在阅读有关密码哈希的知识。 我真的不擅长php。 谁能告诉我如何使用泰勒·霍恩比(Taylor Hornby)的密码哈希函数(如此处所示) ?
2回复

C ++和PHP通用密码哈希标准

我正在寻找一种易于在php和c ++上实现的密码哈希标准。 我知道有BCrypt,但是在c ++上实现起来确实不那么容易。 是否有任何两种语言都易于实现的哈希算法? 我正在寻找它,因为我不想破解myBB论坛。 他们在盐上使用md5,效果不是那么好。 它不能保护我免于被破解。 我知道
2回复

我可以用纯文本形式存储sha256哈希密码吗?

因此,我有php代码,它将密码的哈希版本保存到名为passwords.txt的文件中。 按照目前的状态,知道文件目录(www.example.com/datacache/passwords.txt)的任何人都可以访问它。 这是不正确的方式吗? 我以为我已按照指南对字母进行正确的密码处理,但
6回复

如何安全地存储用户密码?

这比普通的MD5安全多少? 我刚刚开始研究密码安全性。 我对PHP很陌生。
1回复

清理password_hash()的密码

我正在阅读使用password_hash()时的空字节问题。 这给了我两个问题: 从PHP7开始,空字节漏洞是否仍然存在? 我尝试用password_hash()复制它,但要么它已修复,要么我无法复制它。 当\\0之后的字符不同或不存在时, password_verify()返回
1回复

如何获取php hash_pbkdf2的破旧值

我使用PHP hash_pbkdf2函数加密了字符串。 请查看以下代码: 一切都在加密工作正常。 请让我知道如何破坏值“61ea90120ac05230465c”并获得“密码”的结果
4回复

审核我的PHP函数以生成加密安全密码[关闭]

我用PHP编写了一个函数,为我的应用程序生成一个随机密码(仅0-9a-zA-Z) 。 产生的密码必须是加密安全的,并且尽可能随机。 IE浏览器的密码是敏感的。 我要做的最大技巧是每次都洗净$possible字符,因此,即使mt_rand()不是真正随机的,它也不应该是可预测的。
1回复

这种密码哈希和匹配方法的安全性如何?

我从一系列文章中获取了信息,并获得了一些先验知识,以实现以下哈希算法。 但是,关于什么实现是安全的和不安全的讨论很多。 我的方法如何衡量? 安全吗? 那么这种方法安全吗? PHP中是否存在用于对令牌进行哈希处理并稍后与令牌进行匹配的更安全的方法? 任何批评都将受到高度赞赏。
1回复

逆转MD5密码哈希值是否非常有效?

基本上, 因为现在彩虹表和预先计算的攻击可能会打击哈希,但是当攻击者键入计算出的纯文本时,由于原始哈希的计算方式不同,因此它不会被授权。 我可以在我的应用程序上实现吗?