[wp-trac] [WordPress Trac] #21022: Use bcrypt for password hashing; updating old hashes

WordPress Trac noreply at wordpress.org
Wed Sep 18 00:31:11 UTC 2019


#21022: Use bcrypt for password hashing; updating old hashes
-------------------------------------------------+-------------------------
 Reporter:  th23                                 |       Owner:  (none)
     Type:  enhancement                          |      Status:  new
 Priority:  normal                               |   Milestone:  Future
                                                 |  Release
Component:  Security                             |     Version:  3.4
 Severity:  major                                |  Resolution:
 Keywords:  2nd-opinion has-patch needs-testing  |     Focuses:
  dev-feedback                                   |
-------------------------------------------------+-------------------------

Comment (by my1xt):

 @mbijon

 you kinda overlooked something, so let me summarize  (still very long so
 take your time, there are both code examples and math ahead).

 Bcrypt has a 72 length password limit

 how to deal with longer Passwords, just truncating kinda sux, especially
 when we are playing with wordlist passwords?

 You said yourself that passphrases are a strong recommendation, the big
 problem is the bcrypt password length limit though, the idea of wordlist
 passwords us completely right but the entropy per byte of the phrase is
 very low. if we knew the list, we could obciously convert this into a byte
 sequence and be done with it, but we don't.

 The idea of @mobby2561 was to SHA-512 the password and throw THAT into
 bcrypt, basically

 {{{#!php
 <?php
 $prehash=hash("sha512",$password);
 $final_hash=password_hash($prehash,PASSWORD_BCRYPT);
 }}}

 Paragon later meant that the hex output is kinda large with 128 chars and
 suggested to use a base64 hash instead of a hex one, like this:

 {{{#!php
 <?php
 $prehash_bin=hash("sha512",$password,true);
 $prehash_enc=base64_encode($prehash_bin);
 $final_hash=password_hash(%prehash_enc,PASSWORD_BCRYPT);
 }}}

 now the prehash is down to 88 characters, respectable, but we can do
 better, was what I thought, and brought base91 to the table.

 using a little character counting website SHA512 went for 79 characters,
 so basically just 7 characters get thrown out.

 {{{#!php
 <?php
 include("base91.php");

 $prehash_bin=hash("sha512",$password,true);
 $prehash_enc=base91_encode($prehash_bin);
 $final_hash=password_hash(%prehash_enc,PASSWORD_BCRYPT);
 }}}


 so the idea is basically to press as much of a password into the bcrypt as
 we can. obviously a password with more than 512 bits of entropy won't fit
 into SHA-512 without losing some entropy this way but it would fall out
 anyway with normal bcrypt.


 ----
 Time for some Math:

 the idea is that if we say go for a more optimal case and assume we have a
 really big wordlist (the one I extract from 1password usually has around
 18k words, the one I got a few weeks ago is 18 319, it is 131 879 bytes
 long, subtracting 18318 (newlines) from it we get 113 561. dividing that
 by 18 319 gives us an average of 6,2 characters per word.

 I think I am pretty generous here, diceware only comes along with 7776
 words, so yeah you will probably need a LOT more characters to get the
 same amount of entropy.

 so now we need some harder math so take a breath, look at this and let me
 explain every step.

 https://www.wolframalpha.com/input/?i=log18319(2^512)*6.2

 from the inside to outside I do the following.

 first I let it calculate the possibilites for a 512-bit secure password,
 aka before we break off the entropy from SHA512.

 second I use the log with a base of 18319 to calculate how many words are
 needed for that
 (to clarify a log with base (say 2) of a number (say 8) = x solves the
 question
 2^x^ = 8 with x being obviously 3)

 that is about 36 words, quite a lot and most people wont use that sure.

 finally we multiply by 6,2 (the average word length and get (not including
 any spaces) 224 characters before we reach an entropy of 512 bits. no way
 that's gonna fit into bcrypt.

 on the other hand This equation:
 [https://www.wolframalpha.com/input/?i=log2(18319^(72%2F6.2))]

 tells us how much we CAN fit into an average 72 character wordlist
 password based on the assumptions. around 164 bit, which is definitely
 VERY good for a password, but reminder that WP currently has had a 4096
 character limit for passwords. a straight cut to 72 would be a but
 dramatic

 so after the main math is out let's talk a bit more about the cutting.

 the hex sha512 cut 128 to 72, we are down to 288 bit, base64 went down
 from 88 characters, 418,9 bit, I think we can see where this is going, and
 finally base91 with 79 chars has 466,6 bit after the 72 character
 truncation

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/21022#comment:116>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list