在PHP中这是一个很好的散列密码函数吗?如果没有,为什么不呢?

时间:2021-06-14 06:20:32

I'm wondering if this function (which is in part taken from a ~2 year old phpBB version), is good enough.

我想知道这个函数(部分取自2年前的phpBB版本)是否足够好。

If not, why?
And how would you change it (making the transition seamless for existing users) ?

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

The result of hash_pwd() is what will be saved in a DB.

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;
}

4 个解决方案

#1


52  

The code that you have given is a port of PHPASS, specifically the "portable" algorithm. Note the qualification of portable. This will only apply to the phpass library if you pass true as the second constructor parameter. From here on out in this answer, phpass refers ONLY to the portable algorithm, and not the library itself. The library will do bcrypt by default if you do not explicitly specify portable...

您给出的代码是PHPASS的一个端口,特别是“可移植”算法。注意便携性的限定。如果您将true作为第二个构造函数参数传递,那么这将只适用于phpass库。从这里开始,在这个答案中,phpass只指可移植算法,而不是库本身。如果您没有显式地指定可移植的,那么库将默认执行bcrypt。

The PHPBB team did not develop this themselves (a very good thing), but ported it from phpass directly (arguable).

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

There are a few questions we should ask here:

这里有几个问题我们要问:

Is It Bad?

The short answer is no, it's not bad. It offers pretty good security. If you have code on this right now, I wouldn't be in a rush to get off it. It's adequate for most usages. But with that said, there are far better alternatives if you were starting a new project that I wouldn't pick it.

简短的回答是不,还不错。它提供了很好的安全性。如果你现在有这方面的代码,我就不会急于摆脱它。这对于大多数用法来说是足够的。但话虽如此,如果你开始一个我不会选的新项目,还有更好的选择。

What are some weaknesses?

  • Relative To pbkdf2: The phpass algorithm uses hash() where pbkdf2() uses hash_hmac(). Now, a HMAC runs 2 hashes for every call internally, but the PHP implementation only takes approximately 1.6 times the execution of a single call to hash() (isn't C wonderful?). So we get 2 hashes from hash_hmac in 62% of the time it would take hash() to execute 2 hashes.

    相对于pbkdf2: phpass算法使用hash(),其中pbkdf2()使用hash_hmac()。现在,HMAC在内部为每个调用运行2个散列,但是PHP实现只需要执行一次对hash()的调用的1.6倍(难道C不好吗?)因此,我们从hash_hmac中得到2个散列,在62%的时间里,它会使用散列()来执行2个散列。

    What does that mean? Well, for a given runtime, pbkdf2 will run approximately 37.5% more hashes than the phpass algorithm. More hashes in a given time == good, because it results in more computation being performed.

    这是什么意思?对于给定的运行时,pbkdf2将比phpass算法多运行大约37.5%的散列。在给定的时间内执行更多的散列== =好,因为这会导致执行更多的计算。

    So pbkdf2 is approximately 37.5% stronger than phpass when using the same primitive (md5 in this case). But pbkdf2 can also take stronger primitives. So we can use pbkdf2 with sha512 to gain a very significant advantage over the phpass algorithm (mainly because sha512 is a harder algorithm with more computation than md5).

    所以当使用相同的原语时,pbkdf2大约比phpass强37.5%(在本例中是md5)。但是pbkdf2也可以使用更强的原语。所以我们可以使用pbkdf2和sha512来获得比phpass算法非常显著的优势(主要是因为sha512是一种比md5计算量更多的硬算法)。

    This means that not only is pbkdf2 able to generate more computations in the same amount of time, it's able to generate harder computations.

    这意味着pbkdf2不仅能够在相同的时间内生成更多的计算,它还能够生成更复杂的计算。

    With that said, the difference isn't overly significant. It's very much measurable, and pbkdf2 is definitely "stronger" than phpass.

    尽管如此,两者之间的差异并不显著。pbkdf2绝对比phpass“更强”。

  • Relative To bcrypt: This is a lot harder of a comparison to make. But let's look at the surface of it. phpass uses md5, and a loop in PHP. pbkdf2 uses any primitive (in C) and a loop in PHP. bcrypt uses a custom algorithm all in C (meaning it's a different algorithm from any available hash). So right of the bat, bcrypt has a significant advantage just do to the fact that the algorithm is all in C. This allows for more "computation" per unit time. Thereby making it a more efficient slow algorithm (more computations in the given runtime).

    相对于bcrypt:这个比较很难。但是让我们看看它的表面。phpass使用md5,在PHP中使用循环。pbkdf2使用任何原语(C)和PHP中的循环。bcrypt使用的都是C语言的自定义算法(这意味着它与任何可用散列都是不同的算法)。因此,bcrypt在bat中有一个显著的优势,那就是算法都在c中,这就允许每单位时间进行更多的“计算”。从而使它成为一个更有效的慢算法(在给定的运行时中进行更多的计算)。

    But just as important as how many computations it does is the quality of the computations. This could an entire research paper, but in short it comes down to the fact that the computations that bcrypt uses internally are much harder to perform than a normal hash function.

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

    One example of the stronger nature of bcrypt is the fact that bcrypt uses a far larger internal state than a normal hash function. SHA512 uses a 512 bit internal state to compute against a block of 1024 bits. bcrypt uses instead about 32kb of internal state to compute against a single block of 576 bits. The fact that bcrypt's internal state is so much bigger than SHA512 (and md5 and phpass) partially accounts for the stronger nature of bcrypt.

    bcrypt较强特性的一个例子是,bcrypt使用的内部状态要比普通的散列函数大得多。SHA512使用一个512位的内部状态来计算1024位的块。bcrypt使用大约32kb的内部状态对一个576位的块进行计算。bcrypt的内部状态比SHA512(以及md5和phpass)要大得多,这在一定程度上解释了bcrypt的强大特性。

Should It Be Avoided

For new projects, absolutely. It's not that it's bad. It isn't. It's that there are demonstrably stronger algorithms out there (by orders of magnitude). So why not use them?

对于新项目,绝对的。并不是说它不好。它不是。这里有明显更强大的算法(按数量级)。那么为什么不使用它们呢?

For further proof of how bcrypt is stronger, check out the Slides from Password13 (PDF) which launched a 25 GPU cluster for cracking password hashes. Here are the relevant results:

为了进一步证明bcrypt更强大,请查看Password13 (PDF)的幻灯片,它启动了一个25 GPU集群,用于破解密码散列。以下是相关结果:

  • md5($password)
    • 180 BILLION guesses per second
    • 每秒1800亿次猜测
    • 9.4 Hours - All possible 8 character passwords
    • 9.4小时-所有可能的8个字符密码
  • md5($password)每秒1800亿次猜测9.4小时——所有可能的8个字符密码
  • sha1($password)
    • 61 BILLION guesses per second
    • 每秒610亿次猜测
    • 27 Hours - All possible 8 character passwords
    • 27小时-所有可能的8个字符密码
  • sha1($password)每秒610亿次猜测27小时——所有可能的8个字符密码
  • md5crypt (which is very similar to phpass with a cost of 10):
    • 77 Million guesses per second
    • 每秒7700万次。
    • 2.5 Years - All possible 8 character passwords
    • 2.5年-所有可能的8个字符密码
  • md5crypt(与phpass非常相似,成本为10):每秒7700万次猜测,每两年半——所有可能的8个字符密码
  • bcrypt with a cost of 5
    • 71 Thousand guesses per second
    • 每秒71000次猜测
    • 2700 Years - All possible 8 character passwords
    • 2700年-所有可能的8个字符密码
  • bcrypt的代价是每秒57.1万次猜测,总共有8个字符的密码

Note: all possible 8 character passwords are using a 94 character set:

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

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

The Bottom Line

So if you're writing new code, without a doubt use bcrypt. If you have phpass or pbkdf2 in production now, you may want to upgrade, but it's not a clear cut "you're significantly vulnerable".

因此,如果您正在编写新代码,请毫无疑问地使用bcrypt。如果你现在在生产中有phpass或pbkdf2,你可能想要升级,但这不是一个明显的削减“你很容易受到伤害”。

#2


19  

Quick answer:

快速回答:

Use bcrypt (when it is ready) or password_compat library from ircmaxell - it's a bcrypt library.

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

Long answer:

长一点的回答:

This is too complex and outdated for current technology. Md5 should be avoided and just salting isn't good enough. Use bcrypt and save yourself the headache.

这对于当前的技术来说太复杂和过时了。Md5应该避免,仅仅用盐腌是不够的。使用bcrypt来避免头痛。

You might ask yourself why that specific library? Well the same functions will be available in php 5.5 so you won't have to change any coding. Best of luck and keep it simple and efficient. Also slow is good for logging in and password stuff.

你可能会问自己为什么会有这个特定的库?同样的函数在php 5。5中也有,所以你不需要修改任何代码。祝你好运,保持简单高效。同样,slow也适合登录和输入密码。

Update 1

更新1

@ Gumbo -> No MD5 is not broken, but the main purpose of hashes like MD5 now and in the past was for file checking (as you know to check if the contents of the file can be trusted NOT password storage) as hashes are very quick to decipher since you wouldn't use Bcrypt to check the contents of file since you wait for 30 - 45 seconds... So this means that a hash was specifically meant to be read quickly. Even a SHA512 compared to bcrypt is still inferior completely. Thats why it is imperative to push for strong password algorithms like Blowfish/Bcrypt in PHP. We as users and programmers alike must expand the knowledge that plain password storing or low level hashing algorithms ARE NOT the answer - and should never be used for such sensitive information.

@秋葵- >不MD5不是坏了,但现在像MD5散列的主要目的和过去的文件检查(如你所知,以检查是否可以信任文件的内容没有密码存储)解读作为散列非常快速,因为你不会使用Bcrypt检查文件的内容,因为你等待30 - 45秒……这意味着哈希表是专门用来快速读取的。即使是SHA512与bcrypt相比,也完全是次等的。这就是为什么必须在PHP中推出强大的密码算法,比如Blowfish/Bcrypt。作为用户和程序员,我们都必须认识到,普通密码存储或低级别散列算法并不是解决问题的方法,而且永远不应该用于此类敏感信息。

Now to the OP to make your transition over to the new system you would first send a notification to all users stating that "For your security the password encryption system has been updated ........", then you would ask them for a one time password update, once you do the password update you would use the the function called password_verify and if you want to have maximum control of your cost ratio's you use password_needs_rehash if for some reason you choose to change the cost associated with the passwords.

现在,为了将您的过渡到新的系统,您将首先向所有用户发送一条通知,说明“为了您的安全,密码加密系统已被更新……”,然后你会问他们更新一次密码,一旦你的密码更新您将使用调用的函数password_verify如果你想控制你的成本比率最大的使用password_needs_rehash如果由于某种原因你选择改变与密码相关的成本。

This won't take a massive block of code to do this as the gains you would receive in pass word protection out weigh the negatives of having to "recode" the new password system.

这并不需要大量的代码来完成,因为你在密码保护中获得的收益要比不得不“重新编码”新密码系统的负面影响要大。

Hopefully this answers most questions, but none the less IRCmaxell's answer is far superior further going into detail on different algorithms! Best of luck OP, and a big thanks to ircmaxell!

希望这能回答大部分的问题,但是IRCmaxell的答案在深入研究不同算法的细节上更胜一筹!祝你好运,也非常感谢伊克玛克赛尔!

Update 2

更新2

Also, would a password stored like this be actually crackable? how? (I'm getting curious now)

而且,像这样存储的密码真的可以破解吗?如何?(现在我越来越好奇)

Any thing and everything is broken is what my Network security professor tells me.. I laughed at him. Now that I see things in his eyes... well yes.. that is absolutely true!

我的网络安全教授告诉我,任何东西都是坏的。我嘲笑他。现在我从他的眼中看到了一切……是的. .那绝对是真的!

Bcrypt CURRENTLY is the best method of storing passwords! However if you look into Scrypt that seems to be promising but not supported by PHP. None the less any thing and everything is broken, its just a matter of time until some "geek" in a basement will crack Bcrypt. But for now we are safe.. just like we are safe with IPv4 never running out.... oh wait?... ;)

Bcrypt是目前保存密码最好的方法!但是,如果您查看Scrypt,您会发现它似乎很有前途,但是PHP不支持它。尽管如此,所有的东西和所有的东西都坏了,这只是时间问题,直到地下室里的某个“极客”打破了地下室。但是现在我们是安全的。就像我们是安全与IPv4永远不会耗尽....哦,等一下?,)

Hopefully this answers your issue that you brought up sir. Also just to put it into context my system is at a cost of 17 and it takes ~20 - ~30 seconds for logging in, but when I presented the system to my professor and my clients and why it should be mandatory they loved it and felt reassured that they were protected.

希望这回答了你的问题,你也长大先生。就把它放到上下文我系统是在17岁,需要成本~ 20 ~ 30秒的登录,但是当我提出系统我的教授和我的客户,为什么要强制他们喜欢它,感到放心,保护。

#3


1  

I would go for bcrypt.It is good Besides incorporating a salt to protect against rainbow table attacks, bcrypt is an adaptive function: over time, the iteration count can be increased to make it slower, so it remains resistant to brute-force search attacks even with increasing computation power.

我会选择bcrypt。bcrypt是一种自适应功能:随着时间的推移,可以增加迭代计数,使其变得更慢,因此即使在计算能力增加的情况下,它仍然能够抵抗蛮力搜索攻击。

Implementation: How do you use bcrypt for hashing passwords in PHP?

实现:如何在PHP中使用bcrypt对密码进行哈希?

#4


-5  

(Sorry for my English at first)

(对不起,我刚开始学英语)

There is few questions, which all of commenters have to ask before answering:

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

Where will be that code used?

代码将在哪里使用?

What kind of data it will protect?

它将保护什么样的数据?

Will it be used for critical-level system?

是否用于临界水平系统?

Ok we have some use-case. I am using simplified password generator for out IS, yes it is really not '3rd World War ready', but the chance, that user will tell password to someone, or it will be leaked by some malware from his computer is still much bigger.

我们有一些用例。我正在使用简化密码生成器输出,是的,这真的不是“第三次世界大战准备好了”,但是,这个用户将告诉某人密码,或者它将被一些恶意软件从他的电脑中泄露的可能性更大。

  • md5 is weak, use newest fingerprint generator (sha128,sha256,sha512)
  • md5弱,采用最新的指纹发生器(sha128,sha256,sha512)
  • use random length salt like:

    使用任意长度的盐:

    private function generateSalt() {
      $salt = '';
      $i = rand(20, 40); //min,max length
      for($length = 0; $length < $i; $length++) {
        $salt .= chr(rand(33, 126));
      }        
      return $salt;
    }
    
  • then generate some password:

    然后生成一些密码:

    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 :)
    }
    
  • yes password should be stronger, but user will never remember it, it will be saved to browser or written somewhere. Expectations and security versus reality.

    是的,密码应该更强,但用户永远不会记住它,它将被保存到浏览器或其他地方。期望与安全与现实。

    $newSalt = $this->generateSalt();
    $newPass = $this->generatePass();
    $newHash = hash('sha512', $newPass.':'.$newSalt); 
    // now store hash and salt into database
    
  • There is new hash, but it is not over, true work has begun:

    有新的杂凑,但还没有结束,真正的工作已经开始:

    1. logging
    2. 日志记录
    3. session protecting
    4. 会话保护
    5. user,user+ip,ip temp/perm banning
    6. 用户、用户+ ip ip temp /烫禁止
    7. etc

login+logout+re/generate password: 1 or 2 SQL tables and few kb of code

登录+注销+重新生成密码:1或2个SQL表和少量kb代码

other things about security: many tables, really more than few kb of code

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

#1


52  

The code that you have given is a port of PHPASS, specifically the "portable" algorithm. Note the qualification of portable. This will only apply to the phpass library if you pass true as the second constructor parameter. From here on out in this answer, phpass refers ONLY to the portable algorithm, and not the library itself. The library will do bcrypt by default if you do not explicitly specify portable...

您给出的代码是PHPASS的一个端口,特别是“可移植”算法。注意便携性的限定。如果您将true作为第二个构造函数参数传递,那么这将只适用于phpass库。从这里开始,在这个答案中,phpass只指可移植算法,而不是库本身。如果您没有显式地指定可移植的,那么库将默认执行bcrypt。

The PHPBB team did not develop this themselves (a very good thing), but ported it from phpass directly (arguable).

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

There are a few questions we should ask here:

这里有几个问题我们要问:

Is It Bad?

The short answer is no, it's not bad. It offers pretty good security. If you have code on this right now, I wouldn't be in a rush to get off it. It's adequate for most usages. But with that said, there are far better alternatives if you were starting a new project that I wouldn't pick it.

简短的回答是不,还不错。它提供了很好的安全性。如果你现在有这方面的代码,我就不会急于摆脱它。这对于大多数用法来说是足够的。但话虽如此,如果你开始一个我不会选的新项目,还有更好的选择。

What are some weaknesses?

  • Relative To pbkdf2: The phpass algorithm uses hash() where pbkdf2() uses hash_hmac(). Now, a HMAC runs 2 hashes for every call internally, but the PHP implementation only takes approximately 1.6 times the execution of a single call to hash() (isn't C wonderful?). So we get 2 hashes from hash_hmac in 62% of the time it would take hash() to execute 2 hashes.

    相对于pbkdf2: phpass算法使用hash(),其中pbkdf2()使用hash_hmac()。现在,HMAC在内部为每个调用运行2个散列,但是PHP实现只需要执行一次对hash()的调用的1.6倍(难道C不好吗?)因此,我们从hash_hmac中得到2个散列,在62%的时间里,它会使用散列()来执行2个散列。

    What does that mean? Well, for a given runtime, pbkdf2 will run approximately 37.5% more hashes than the phpass algorithm. More hashes in a given time == good, because it results in more computation being performed.

    这是什么意思?对于给定的运行时,pbkdf2将比phpass算法多运行大约37.5%的散列。在给定的时间内执行更多的散列== =好,因为这会导致执行更多的计算。

    So pbkdf2 is approximately 37.5% stronger than phpass when using the same primitive (md5 in this case). But pbkdf2 can also take stronger primitives. So we can use pbkdf2 with sha512 to gain a very significant advantage over the phpass algorithm (mainly because sha512 is a harder algorithm with more computation than md5).

    所以当使用相同的原语时,pbkdf2大约比phpass强37.5%(在本例中是md5)。但是pbkdf2也可以使用更强的原语。所以我们可以使用pbkdf2和sha512来获得比phpass算法非常显著的优势(主要是因为sha512是一种比md5计算量更多的硬算法)。

    This means that not only is pbkdf2 able to generate more computations in the same amount of time, it's able to generate harder computations.

    这意味着pbkdf2不仅能够在相同的时间内生成更多的计算,它还能够生成更复杂的计算。

    With that said, the difference isn't overly significant. It's very much measurable, and pbkdf2 is definitely "stronger" than phpass.

    尽管如此,两者之间的差异并不显著。pbkdf2绝对比phpass“更强”。

  • Relative To bcrypt: This is a lot harder of a comparison to make. But let's look at the surface of it. phpass uses md5, and a loop in PHP. pbkdf2 uses any primitive (in C) and a loop in PHP. bcrypt uses a custom algorithm all in C (meaning it's a different algorithm from any available hash). So right of the bat, bcrypt has a significant advantage just do to the fact that the algorithm is all in C. This allows for more "computation" per unit time. Thereby making it a more efficient slow algorithm (more computations in the given runtime).

    相对于bcrypt:这个比较很难。但是让我们看看它的表面。phpass使用md5,在PHP中使用循环。pbkdf2使用任何原语(C)和PHP中的循环。bcrypt使用的都是C语言的自定义算法(这意味着它与任何可用散列都是不同的算法)。因此,bcrypt在bat中有一个显著的优势,那就是算法都在c中,这就允许每单位时间进行更多的“计算”。从而使它成为一个更有效的慢算法(在给定的运行时中进行更多的计算)。

    But just as important as how many computations it does is the quality of the computations. This could an entire research paper, but in short it comes down to the fact that the computations that bcrypt uses internally are much harder to perform than a normal hash function.

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

    One example of the stronger nature of bcrypt is the fact that bcrypt uses a far larger internal state than a normal hash function. SHA512 uses a 512 bit internal state to compute against a block of 1024 bits. bcrypt uses instead about 32kb of internal state to compute against a single block of 576 bits. The fact that bcrypt's internal state is so much bigger than SHA512 (and md5 and phpass) partially accounts for the stronger nature of bcrypt.

    bcrypt较强特性的一个例子是,bcrypt使用的内部状态要比普通的散列函数大得多。SHA512使用一个512位的内部状态来计算1024位的块。bcrypt使用大约32kb的内部状态对一个576位的块进行计算。bcrypt的内部状态比SHA512(以及md5和phpass)要大得多,这在一定程度上解释了bcrypt的强大特性。

Should It Be Avoided

For new projects, absolutely. It's not that it's bad. It isn't. It's that there are demonstrably stronger algorithms out there (by orders of magnitude). So why not use them?

对于新项目,绝对的。并不是说它不好。它不是。这里有明显更强大的算法(按数量级)。那么为什么不使用它们呢?

For further proof of how bcrypt is stronger, check out the Slides from Password13 (PDF) which launched a 25 GPU cluster for cracking password hashes. Here are the relevant results:

为了进一步证明bcrypt更强大,请查看Password13 (PDF)的幻灯片,它启动了一个25 GPU集群,用于破解密码散列。以下是相关结果:

  • md5($password)
    • 180 BILLION guesses per second
    • 每秒1800亿次猜测
    • 9.4 Hours - All possible 8 character passwords
    • 9.4小时-所有可能的8个字符密码
  • md5($password)每秒1800亿次猜测9.4小时——所有可能的8个字符密码
  • sha1($password)
    • 61 BILLION guesses per second
    • 每秒610亿次猜测
    • 27 Hours - All possible 8 character passwords
    • 27小时-所有可能的8个字符密码
  • sha1($password)每秒610亿次猜测27小时——所有可能的8个字符密码
  • md5crypt (which is very similar to phpass with a cost of 10):
    • 77 Million guesses per second
    • 每秒7700万次。
    • 2.5 Years - All possible 8 character passwords
    • 2.5年-所有可能的8个字符密码
  • md5crypt(与phpass非常相似,成本为10):每秒7700万次猜测,每两年半——所有可能的8个字符密码
  • bcrypt with a cost of 5
    • 71 Thousand guesses per second
    • 每秒71000次猜测
    • 2700 Years - All possible 8 character passwords
    • 2700年-所有可能的8个字符密码
  • bcrypt的代价是每秒57.1万次猜测,总共有8个字符的密码

Note: all possible 8 character passwords are using a 94 character set:

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

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

The Bottom Line

So if you're writing new code, without a doubt use bcrypt. If you have phpass or pbkdf2 in production now, you may want to upgrade, but it's not a clear cut "you're significantly vulnerable".

因此,如果您正在编写新代码,请毫无疑问地使用bcrypt。如果你现在在生产中有phpass或pbkdf2,你可能想要升级,但这不是一个明显的削减“你很容易受到伤害”。

#2


19  

Quick answer:

快速回答:

Use bcrypt (when it is ready) or password_compat library from ircmaxell - it's a bcrypt library.

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

Long answer:

长一点的回答:

This is too complex and outdated for current technology. Md5 should be avoided and just salting isn't good enough. Use bcrypt and save yourself the headache.

这对于当前的技术来说太复杂和过时了。Md5应该避免,仅仅用盐腌是不够的。使用bcrypt来避免头痛。

You might ask yourself why that specific library? Well the same functions will be available in php 5.5 so you won't have to change any coding. Best of luck and keep it simple and efficient. Also slow is good for logging in and password stuff.

你可能会问自己为什么会有这个特定的库?同样的函数在php 5。5中也有,所以你不需要修改任何代码。祝你好运,保持简单高效。同样,slow也适合登录和输入密码。

Update 1

更新1

@ Gumbo -> No MD5 is not broken, but the main purpose of hashes like MD5 now and in the past was for file checking (as you know to check if the contents of the file can be trusted NOT password storage) as hashes are very quick to decipher since you wouldn't use Bcrypt to check the contents of file since you wait for 30 - 45 seconds... So this means that a hash was specifically meant to be read quickly. Even a SHA512 compared to bcrypt is still inferior completely. Thats why it is imperative to push for strong password algorithms like Blowfish/Bcrypt in PHP. We as users and programmers alike must expand the knowledge that plain password storing or low level hashing algorithms ARE NOT the answer - and should never be used for such sensitive information.

@秋葵- >不MD5不是坏了,但现在像MD5散列的主要目的和过去的文件检查(如你所知,以检查是否可以信任文件的内容没有密码存储)解读作为散列非常快速,因为你不会使用Bcrypt检查文件的内容,因为你等待30 - 45秒……这意味着哈希表是专门用来快速读取的。即使是SHA512与bcrypt相比,也完全是次等的。这就是为什么必须在PHP中推出强大的密码算法,比如Blowfish/Bcrypt。作为用户和程序员,我们都必须认识到,普通密码存储或低级别散列算法并不是解决问题的方法,而且永远不应该用于此类敏感信息。

Now to the OP to make your transition over to the new system you would first send a notification to all users stating that "For your security the password encryption system has been updated ........", then you would ask them for a one time password update, once you do the password update you would use the the function called password_verify and if you want to have maximum control of your cost ratio's you use password_needs_rehash if for some reason you choose to change the cost associated with the passwords.

现在,为了将您的过渡到新的系统,您将首先向所有用户发送一条通知,说明“为了您的安全,密码加密系统已被更新……”,然后你会问他们更新一次密码,一旦你的密码更新您将使用调用的函数password_verify如果你想控制你的成本比率最大的使用password_needs_rehash如果由于某种原因你选择改变与密码相关的成本。

This won't take a massive block of code to do this as the gains you would receive in pass word protection out weigh the negatives of having to "recode" the new password system.

这并不需要大量的代码来完成,因为你在密码保护中获得的收益要比不得不“重新编码”新密码系统的负面影响要大。

Hopefully this answers most questions, but none the less IRCmaxell's answer is far superior further going into detail on different algorithms! Best of luck OP, and a big thanks to ircmaxell!

希望这能回答大部分的问题,但是IRCmaxell的答案在深入研究不同算法的细节上更胜一筹!祝你好运,也非常感谢伊克玛克赛尔!

Update 2

更新2

Also, would a password stored like this be actually crackable? how? (I'm getting curious now)

而且,像这样存储的密码真的可以破解吗?如何?(现在我越来越好奇)

Any thing and everything is broken is what my Network security professor tells me.. I laughed at him. Now that I see things in his eyes... well yes.. that is absolutely true!

我的网络安全教授告诉我,任何东西都是坏的。我嘲笑他。现在我从他的眼中看到了一切……是的. .那绝对是真的!

Bcrypt CURRENTLY is the best method of storing passwords! However if you look into Scrypt that seems to be promising but not supported by PHP. None the less any thing and everything is broken, its just a matter of time until some "geek" in a basement will crack Bcrypt. But for now we are safe.. just like we are safe with IPv4 never running out.... oh wait?... ;)

Bcrypt是目前保存密码最好的方法!但是,如果您查看Scrypt,您会发现它似乎很有前途,但是PHP不支持它。尽管如此,所有的东西和所有的东西都坏了,这只是时间问题,直到地下室里的某个“极客”打破了地下室。但是现在我们是安全的。就像我们是安全与IPv4永远不会耗尽....哦,等一下?,)

Hopefully this answers your issue that you brought up sir. Also just to put it into context my system is at a cost of 17 and it takes ~20 - ~30 seconds for logging in, but when I presented the system to my professor and my clients and why it should be mandatory they loved it and felt reassured that they were protected.

希望这回答了你的问题,你也长大先生。就把它放到上下文我系统是在17岁,需要成本~ 20 ~ 30秒的登录,但是当我提出系统我的教授和我的客户,为什么要强制他们喜欢它,感到放心,保护。

#3


1  

I would go for bcrypt.It is good Besides incorporating a salt to protect against rainbow table attacks, bcrypt is an adaptive function: over time, the iteration count can be increased to make it slower, so it remains resistant to brute-force search attacks even with increasing computation power.

我会选择bcrypt。bcrypt是一种自适应功能:随着时间的推移,可以增加迭代计数,使其变得更慢,因此即使在计算能力增加的情况下,它仍然能够抵抗蛮力搜索攻击。

Implementation: How do you use bcrypt for hashing passwords in PHP?

实现:如何在PHP中使用bcrypt对密码进行哈希?

#4


-5  

(Sorry for my English at first)

(对不起,我刚开始学英语)

There is few questions, which all of commenters have to ask before answering:

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

Where will be that code used?

代码将在哪里使用?

What kind of data it will protect?

它将保护什么样的数据?

Will it be used for critical-level system?

是否用于临界水平系统?

Ok we have some use-case. I am using simplified password generator for out IS, yes it is really not '3rd World War ready', but the chance, that user will tell password to someone, or it will be leaked by some malware from his computer is still much bigger.

我们有一些用例。我正在使用简化密码生成器输出,是的,这真的不是“第三次世界大战准备好了”,但是,这个用户将告诉某人密码,或者它将被一些恶意软件从他的电脑中泄露的可能性更大。

  • md5 is weak, use newest fingerprint generator (sha128,sha256,sha512)
  • md5弱,采用最新的指纹发生器(sha128,sha256,sha512)
  • use random length salt like:

    使用任意长度的盐:

    private function generateSalt() {
      $salt = '';
      $i = rand(20, 40); //min,max length
      for($length = 0; $length < $i; $length++) {
        $salt .= chr(rand(33, 126));
      }        
      return $salt;
    }
    
  • then generate some password:

    然后生成一些密码:

    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 :)
    }
    
  • yes password should be stronger, but user will never remember it, it will be saved to browser or written somewhere. Expectations and security versus reality.

    是的,密码应该更强,但用户永远不会记住它,它将被保存到浏览器或其他地方。期望与安全与现实。

    $newSalt = $this->generateSalt();
    $newPass = $this->generatePass();
    $newHash = hash('sha512', $newPass.':'.$newSalt); 
    // now store hash and salt into database
    
  • There is new hash, but it is not over, true work has begun:

    有新的杂凑,但还没有结束,真正的工作已经开始:

    1. logging
    2. 日志记录
    3. session protecting
    4. 会话保护
    5. user,user+ip,ip temp/perm banning
    6. 用户、用户+ ip ip temp /烫禁止
    7. etc

login+logout+re/generate password: 1 or 2 SQL tables and few kb of code

登录+注销+重新生成密码:1或2个SQL表和少量kb代码

other things about security: many tables, really more than few kb of code

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