This.... from a bank.... I'm.... WTF?!



  •  I generate a password and copy paste it, and this is the message saying it's too long: 

     

    AKA "Your password is too long to consider it strong enough to protect your account. Please enter a shorter password. "

    OK, let's play ball and move on.

    So  we are now at the login screen:

     

    Sounds fair enough, so we try and are... rejected! 

     Wait, what the hell?

    I tried to enter my password in all upper case, but still got rejected. I'm guessing I used some character allowed by the password setter, but not by the password checker. Time to phone them up again...

    Anyone else seen this last screen ANYWHERE else? It's the first time I've seen this crazy shit. 



  •  As a pet peeve I really hate sites that impose a password maximum.  A minimum is bad enough but understandable at least, but a maximum?  What if I want to use an actual phrase/sentence as my password versus some wonky characters?



  • I've never used a service that wanted me to enter my password in all uppercase the first time. I can't even think of a reason why that would ever be a thing.



  • How is it possible to fuck up that badly?


  • Trolleybus Mechanic

    @blakeyrat said:

    How is it possible to fuck up that badly?
     

    There's probably some AS/400 backend. For the longest time, all the text HAS BEEN IN UPPERCASE. So that's how it must always be. It's a mindset. AS/400 is UPPERCASE.  So all fields saved in AS/400 must be in UPPERCASE.

    One web developers starts to speak up "But what about pas..."

    NO! ALL FIELDS MUST BE UPPERCASE BECUASE BANK THAT IS WHY!

    So the password field is saved in uppercase. But since that would fuck up the MD5 hash, they don't hash. I'm sure they don't store it in plaintext, though. I'm sure they save it ROT13, in a field called drowssap (because hackers are only looking for a field called password).

    I am joking, but I am also 100% correct.



  • @blakeyrat said:

    How is it possible to fuck up that badly?

    More importantly, why is Mole's money in a bank that does this that badly?



  • @locallunatic said:

    @blakeyrat said:
    How is it possible to fuck up that badly?

    More importantly, why is Mole's money in a bank that does this that badly?

    Don't worry, it won't be for long, I'm sure



  • @ObiWayneKenobi said:

     As a pet peeve I really hate sites that impose a password maximum.  A minimum is bad enough but understandable at least, but a maximum?  What if I want to use an actual phrase/sentence as my password versus some wonky characters?

    bcrypt limits you to a maximum of 55 bytes and it's practically the best passwd hashing algo out there. (Haven't we had this conversation before?)



  • The ones that really fucking piss me off are the ones that pull shenanigans like this:



  • @anotherusername said:

    The ones that really fucking piss me off are the ones that pull shenanigans like this:

    YESSSSSSSS. That practically had me spitting blood when I first saw it. It's like "I haven't typed a password in years, dumbass."



  • @morbiuswilters said:

    @ObiWayneKenobi said:
    As a pet peeve I really hate sites that impose a password maximum.  A minimum is bad enough but understandable at least, but a maximum?  What if I want to use an actual phrase/sentence as my password versus some wonky characters?
    bcrypt limits you to a maximum of 55 bytes and it's practically the best passwd hashing algo out there. (Haven't we had this conversation before?)

    Yeah but on long inputs you can feed the first set of bytes in, then the second, and so on XORing the outputs (minus the identifiers) and feeding that in to get a final. Of course this doesn't actually deal with the limited input space but it is a way of faking it larger.



  • @locallunatic said:

    @morbiuswilters said:
    @ObiWayneKenobi said:
    As a pet peeve I really hate sites that impose a password maximum.  A minimum is bad enough but understandable at least, but a maximum?  What if I want to use an actual phrase/sentence as my password versus some wonky characters?
    bcrypt limits you to a maximum of 55 bytes and it's practically the best passwd hashing algo out there. (Haven't we had this conversation before?)

    Yeah but on long inputs you can feed the first set of bytes in, then the second, and so on XORing the outputs (minus the identifiers) and feeding that in to get a final. Of course this doesn't actually deal with the limited input space but it is a way of faking it larger.

    Off-the-cuff, that sounds like it would substantially weaken the algo. Do you have a cite on how this works? It's probably just me being paranoid, but I'd like to see a crypto professional explain it.


  • FoxDev

    @blakeyrat said:

    How is it possible to fuck up that badly?

    You must be new here :P



  • @locallunatic said:

    Yeah but on long inputs you can feed the first set of bytes in, then the second, and so on XORing the outputs (minus the identifiers) and feeding that in to get a final. Of course this doesn't actually deal with the limited input space but it is a way of faking it larger.

    Another thing you could do, if you were really committed to this "allowing over 55 chars" thing (personally I'd just tell the user to eff off) is sha-256 the password first, which would give you 64 bytes. Then truncate to 55 and run through bcrypt. Not really beautiful, but simple and I don't think it would substantially impact security.



  • @morbiuswilters said:

    Off-the-cuff, that sounds like it would substantially weaken the algo. Do you have a cite on how this works? It's probably just me being paranoid, but I'd like to see a crypto professional explain it.

    @From wikipedia said:
    Although Provos and Mazières do not state the reason for the shorter restriction, they may have been motivated by the following statement from Bruce Schneier's original specification of Blowfish, "The 448 limit on the key size ensures that the every bit of every subkey depends on every bit of the key."

    The point of XORing the outputs together is so that the (intermediate) result depends on the value from both of the outputs. This gets you some value that isn't (by my understanding, but it's been a while since I dug in on crypto theory) easier to reverse than the output from the shortened inputs which is the point of hashing a password. I guess you could try and just save that output, but then you could tell things about how many times stuff was run based on what happened to the identifiers that are at the start of the output 59-60 bytes so chopping them and re-feeding it to bcrypt would remove that.



  • @locallunatic said:

    @morbiuswilters said:
    Off-the-cuff, that sounds like it would substantially weaken the algo. Do you have a cite on how this works? It's probably just me being paranoid, but I'd like to see a crypto professional explain it.

    @From wikipedia said:
    Although Provos and Mazières do not state the reason for the shorter restriction, they may have been motivated by the following statement from Bruce Schneier's original specification of Blowfish, "The 448 limit on the key size ensures that the every bit of every subkey depends on every bit of the key."

    The point of XORing the outputs together is so that the (intermediate) result depends on the value from both of the outputs. This gets you some value that isn't (by my understanding, but it's been a while since I dug in on crypto theory) easier to reverse than the output from the shortened inputs which is the point of hashing a password. I guess you could try and just save that output, but then you could tell things about how many times stuff was run based on what happened to the identifiers that are at the start of the output 59-60 bytes so chopping them and re-feeding it to bcrypt would remove that.

    I think the argument is that XORing results reduces the entropy of the overall process, essentially "averaging" the entropy of each part.

    Imagine I had two sources of randomness, one produces 0,1,2,3,0,1,2,3... And the other produces 0,1,0,1...

    XORing the results (and truncating to the two bits) gets 0,0,2,2,0,0,2,2... Which has notably lower entropy than the first algorithm


  • Discourse touched me in a no-no place

    @Buttembly Coder said:

    I think the argument is that XORing results reduces the entropy of the overall process, essentially "averaging" the entropy of each part.
    Straight XOR is a problem because the normal space of input characters doesn't set all bits to 0 or 1 with equal frequency. Real crypto hashes are (much!) better at spreading the bits around. They're also quite slow…



  • @Buttembly Coder said:

    I think the argument is that XORing results reduces the entropy of the overall process, essentially "averaging" the entropy of each part.

    Imagine I had two sources of randomness, one produces 0,1,2,3,0,1,2,3... And the other produces 0,1,0,1...

    XORing the results (and truncating to the two bits) gets 0,0,2,2,0,0,2,2... Which has notably lower entropy than the first algorithm

    I don't think I'm understanding what you are saying correctly. That or I was thinking of bit-wise XOR and you are using something else.

  • Discourse touched me in a no-no place

    @locallunatic said:

    The point of XORing the outputs together is so that the (intermediate) result depends on the value from both of the outputs.
    You might as well use an ADD; it's just a fancy XOR (with a propagating carry bit, which is generated from an AND really). More importantly, you've also got to rotate the values so that bits aren't always injected in the same location, or you end up with other weaknesses (like not being able to distinguish between reorderings of letters, which enormously weakens the hash).



  • @locallunatic said:

    I don't think I'm understanding what you are saying correctly. That or I was thinking of bit-wise XOR and you are using something else.

    I was thinking of bitwise XOR. What I'm trying to explain is that, essentially, taking two secure things and combining them into one thing of the same size reduces the secureness. It's an oversimplification, but, essentially, the 55 bytes gives full domain coverage of the output, so putting two results into one through XOR or most (any?) bitwise or similar operation is lossy in terms of entropy, and makes it more likely that a random guess would generate a match. I am quite bad at explaining this.



  • @Lorne Kates said:

    @blakeyrat said:

    How is it possible to fuck up that badly?
     

    There's probably some AS/400 backend. For the longest time, all the text HAS BEEN IN UPPERCASE. So that's how it must always be. It's a mindset. AS/400 is UPPERCASE.  So all fields saved in AS/400 must be in UPPERCASE.

    One web developers starts to speak up "But what about pas..."

    NO! ALL FIELDS MUST BE UPPERCASE BECUASE BANK THAT IS WHY!

    So the password field is saved in uppercase. But since that would fuck up the MD5 hash, they don't hash. I'm sure they don't store it in plaintext, though. I'm sure they save it ROT13, in a field called drowssap (because hackers are only looking for a field called password).

    I am joking, but I am also 100% correct.




    AS/400 passwords are indeed all uppercase. And maddening. It also explains the strict size limit, AS/400 password field is limited to 10char I believe.



  • @Buttembly Coder said:

    putting two results into one through XOR or most (any?) bitwise or similar operation is lossy in terms of entropy, and makes it more likely that a random guess would generate a match. I am quite bad at explaining this.
    May I try? Thank you.

    Let's say hashing the first part of the input produces some result A, and hashing the second part produces result B. Let's say, for the sake of simplicity, that it's a really good algorithm, and there is only one input that can produce any given output. If you XOR A and B to get C, there are a whole bunch of A and B that satisfy A XOR B == C. Now there are a whole bunch of inputs that can generate a match on the result. Actually, the more bits in C, the more possible matches there are.



  • @darkmattar said:

    @Lorne Kates said:

    @blakeyrat said:

    How is it possible to fuck up that badly?
     

    There's probably some AS/400 backend. For the longest time, all the text HAS BEEN IN UPPERCASE. So that's how it must always be. It's a mindset. AS/400 is UPPERCASE.  So all fields saved in AS/400 must be in UPPERCASE.

    One web developers starts to speak up "But what about pas..."

    NO! ALL FIELDS MUST BE UPPERCASE BECUASE BANK THAT IS WHY!

    So the password field is saved in uppercase. But since that would fuck up the MD5 hash, they don't hash. I'm sure they don't store it in plaintext, though. I'm sure they save it ROT13, in a field called drowssap (because hackers are only looking for a field called password).

    I am joking, but I am also 100% correct.




    AS/400 passwords are indeed all uppercase. And maddening. It also explains the strict size limit, AS/400 password field is limited to 10char I believe.

    That doesn't actually explain why they make you uppercase the password yourself (no uppercase function in their language?) and only on the first time.



  • @HardwareGeek said:

    @Buttembly Coder said:
    I am quite bad at explaining this.
    May I try? Thank you.

    Let's say hashing the first part of the input produces some result A, and hashing the second part produces result B. Let's say, for the sake of simplicity, that it's a really good algorithm, and there is only one input that can produce any given output. If you XOR A and B to get C, there are a whole bunch of A and B that satisfy A XOR B == C. Now there are a whole bunch of inputs that can generate a match on the result. Actually, the more bits in C, the more possible matches there are.


    Thank you, that is a much more concise explanation



  • @HardwareGeek said:

    @Buttembly Coder said:
    putting two results into one through XOR or most (any?) bitwise or similar operation is lossy in terms of entropy, and makes it more likely that a random guess would generate a match. I am quite bad at explaining this.
    May I try? Thank you.

    Let's say hashing the first part of the input produces some result A, and hashing the second part produces result B. Let's say, for the sake of simplicity, that it's a really good algorithm, and there is only one input that can produce any given output. If you XOR A and B to get C, there are a whole bunch of A and B that satisfy A XOR B == C. Now there are a whole bunch of inputs that can generate a match on the result. Actually, the more bits in C, the more possible matches there are.

    Although that probably doesn't matter for password-hashing. What worries me more--and bear with me, because it's been many years since I looked at the internals of bcrypt--is that the way bcrypt works is it more-or-less uses the password itself as a key for a block cipher (hence the 55b limit.) So you'd be taking the output, xoring it with the next part of the password and then feeding that back in as a new key. That makes me really nervous.


  • Discourse touched me in a no-no place

    @morbiuswilters said:

    Although that probably doesn't matter for password-hashing. What worries me more--and bear with me, because it's been many years since I looked at the internals of bcrypt--is that the way bcrypt works is it more-or-less uses the password itself as a key for a block cipher (hence the 55b limit.) So you'd be taking the output, xoring it with the next part of the password and then feeding that back in as a new key. That makes me really nervous.
    If the algorithm is right, that's OK. I've not seen any word that bcrypt is problematic, so the algorithm (probably) is right.



  • @morbiuswilters said:

    So you'd be taking the output, xoring it with the next part of the password and then feeding that back in as a new key. That makes me really nervous.
     

    This just has the same feel as reusing a one time pad, doesn't it? Maybe it isn't - I'm certainly not Bruce Schneier - but it still feels icky.


  • Trolleybus Mechanic

    @morbiuswilters said:

    That doesn't actually explain why they make you uppercase the password yourself (no uppercase function in their language?) and only on the first time.
     

    Did you miss that part about "It's a mindset"?  Passwords are UPPERCASE.  "But we can let people enter lower case and then--"  I SAID PASSWORD ARE UPPERCASE? DO YOU NOT UNDERSTAND?!?! DO WHAT I SAY!

    If you could assume enough competency to use a .ToUpper() function instead of pestering the end user, this WTF would never have happened in the first place. It's a stupid mindset all the way down.



  • @Lorne Kates said:

    @morbiuswilters said:

    That doesn't actually explain why they make you uppercase the password yourself (no uppercase function in their language?) and only on the first time.
     

    Did you miss that part about "It's a mindset"?  Passwords are UPPERCASE.  "But we can let people enter lower case and then--"  I SAID PASSWORD ARE UPPERCASE? DO YOU NOT UNDERSTAND?!?! DO WHAT I SAY!

    If you could assume enough competency to use a .ToUpper() function instead of pestering the end user, this WTF would never have happened in the first place. It's a stupid mindset all the way down.

    You're right, I shouldn't try to find rational thought where there is none to be found. Beg pardon, m'lord.



  • @morbiuswilters said:

    @ObiWayneKenobi said:

     As a pet peeve I really hate sites that impose a password maximum.  A minimum is bad enough but understandable at least, but a maximum?  What if I want to use an actual phrase/sentence as my password versus some wonky characters?

    bcrypt limits you to a maximum of 55 bytes and it's practically the best passwd hashing algo out there. (Haven't we had this conversation before?)

    55 bytes? I thought it was 72 bytes!



  • @Ben L. said:

    @morbiuswilters said:
    @ObiWayneKenobi said:

     As a pet peeve I really hate sites that impose a password maximum.  A minimum is bad enough but understandable at least, but a maximum?  What if I want to use an actual phrase/sentence as my password versus some wonky characters?

    bcrypt limits you to a maximum of 55 bytes and it's practically the best passwd hashing algo out there. (Haven't we had this conversation before?)

    55 bytes? I thought it was 72 bytes!

    Well, you're wrong. It uses 72 bytes internally but it limits you to 56 bytes (55 ASCII chars and a NUL).



  • @anotherusername said:

    The ones that really fucking piss me off are the ones that pull shenanigans like this:

    Until you realize that Paypal doesn't do server side validation (or they didn't when I did it), so if you submit the form manually, you can have whatever password you want.

    :)



  •  And I thought my bank was bad when it took them 3 days to update OpenSSL and a week to get a new SSL certificate (OK, not really the banks fault probably).



  • @mahlerrd said:

    @morbiuswilters said:

    So you'd be taking the output, xoring it with the next part of the password and then feeding that back in as a new key. That makes me really nervous.
     

    This just has the same feel as reusing a one time pad, doesn't it? Maybe it isn't - I'm certainly not Bruce Schneier - but it still feels icky.

    No, it isn't. It's CBC mode.



  • @Lorne Kates said:

    Did you miss that part about "It's a mindset"?  Passwords are UPPERCASE.  "But we can let people enter lower case and then--"  I SAID PASSWORD ARE UPPERCASE? DO YOU NOT UNDERSTAND?!?! DO WHAT I SAY!

    If you could assume enough competency to use a .ToUpper() function instead of pestering the end user, this WTF would never have happened in the first place. It's a stupid mindset all the way down.


    This was the exact mindset that led to certain internal webapps having no case sensitivity at a place I used to work. There was still a fear of changing those apps to be case sensitive too, despite EVERYTHING else being case sensitive (other than the as/400 of course).


    I was the one tasked with bringing things at least a little bit more up to snuff. You know, hash the passwords and such. Lo and behold, I used the very .ToUpper() function on the login script, just as Lorne mentions, rather than forcing the users to ever figure out what case their password was in. Everyone was happy on both sides.


    Another AS/400 thing... they still had DEVELOPERS running 800x600 resolution on 22" monitors because that's the size their as/400 terminal is. On the upside, they did at least understand why no modern application bothered to support displaying on their shitty screen.



  • @DaveK said:

    @mahlerrd said:

    @morbiuswilters said:

    So you'd be taking the output, xoring it with the next part of the password and then feeding that back in as a new key. That makes me really nervous.
     

    This just has the same feel as reusing a one time pad, doesn't it? Maybe it isn't - I'm certainly not Bruce Schneier - but it still feels icky.

    No, it isn't. It's CBC mode.

    Not exactly, CBC xors the last block's ciphertext with the current block's plaintext before encrypting it. Whereas this would be xoring the last block's ciphertext with the key from the last block. So the key would be effectively changing each block.

    From a practical standpoint, it may end up working similar to CBC but it does not feel correct.



  • @darkmattar said:

    @Lorne Kates said:

    Did you miss that part about "It's a mindset"?  Passwords are UPPERCASE.  "But we can let people enter lower case and then--"  I SAID PASSWORD ARE UPPERCASE? DO YOU NOT UNDERSTAND?!?! DO WHAT I SAY!

    If you could assume enough competency to use a .ToUpper() function instead of pestering the end user, this WTF would never have happened in the first place. It's a stupid mindset all the way down.


    This was the exact mindset that led to certain internal webapps having no case sensitivity at a place I used to work. There was still a fear of changing those apps to be case sensitive too, despite EVERYTHING else being case sensitive (other than the as/400 of course).


    I was the one tasked with bringing things at least a little bit more up to snuff. You know, hash the passwords and such. Lo and behold, I used the very .ToUpper() function on the login script, just as Lorne mentions, rather than forcing the users to ever figure out what case their password was in. Everyone was happy on both sides.


    Another AS/400 thing... they still had DEVELOPERS running 800x600 resolution on 22" monitors because that's the size their as/400 terminal is. On the upside, they did at least understand why no modern application bothered to support displaying on their shitty screen.

    AS/400: Linux's Linux


  • Discourse touched me in a no-no place

    @Lorne Kates said:

    some AS/400 backend
    I keep reading that as “Ass 400”.



  • @morbiuswilters said:

    @locallunatic said:
    Yeah but on long inputs you can feed the first set of bytes in, then the second, and so on XORing the outputs (minus the identifiers) and feeding that in to get a final. Of course this doesn't actually deal with the limited input space but it is a way of faking it larger.

    Another thing you could do, if you were really committed to this "allowing over 55 chars" thing (personally I'd just tell the user to eff off) is sha-256 the password first, which would give you 64 bytes. Then truncate to 55 and run through bcrypt. Not really beautiful, but simple and I don't think it would substantially impact security.

    SHA-256 gives you a 32 byte result, not 64, so you wouldn't even need to truncate it. And no, doing this would have no impact on security.

    Bcrypt works by encrypting the 192 bit value "OrpheanBeholderScryDoubt" with a key derived from the password you pass in, so each possible input value maps to some output value within a 2192 range. That's big enough that collisions are negligibly unlikely: According to the birthday formula n(p, d) ≈ √(2d ln(1 / (1 - p))), your database would need to store bcrypts of over a hundred billion billion unique passwords to make a duplicate bcrypt result more likely than an uncorrectable hard disk error.

    SHA-256 has an output range 264 times bigger again, which makes it a billions of times less likely than bcrypt itself to generate any such collision. In practice you'd always see a one-to-one mapping between passphrase, SHA-256 hash and bcrypt result.



  • @DaveK said:

    No, it isn't. It's CBC mode.
     

     Oh, good then.  Last night as I was lying awake wondering just how much snow we were going to end up with, I realized that it shouldn't be an issue in this case.  Glad you experts confirmed it.



  • @flabdablet said:

    SHA-256 gives you a 32 byte result, not 64, so you wouldn't even need to truncate it. And no, doing this would have no impact on security.

    Crap, I must have a brain tumor. Yeah, there's an argument for using SHA-512 and truncating to 55 bytes, but just using SHA-256 would really be sufficient.

    @flabdablet said:

    SHA-256 has an output range 264 times bigger again, which makes it a billions of times less likely than bcrypt itself to generate any such collision. In practice you'd always see a one-to-one mapping between passphrase, SHA-256 hash and bcrypt result.

    bcrypt is salted, though, so if you're using it correctly the resulting bcrypt hash should differ, even if every single input password (and thus SHA-256/-512 hash) is the same. Unless you use the same salt twice, but IIRC it uses a 16-byte salt so the likelihood of two users using the same password and getting the same salt is low. (And if you have so many duplicate passwords that it's a real concern, something is effed.)



  • @morbiuswilters said:

    bcrypt is salted, though, so if you're using it correctly the resulting bcrypt hash should differ, even if every single input password (and thus SHA-256/-512 hash) is the same. Unless you use the same salt twice, but IIRC it uses a 16-byte salt so the likelihood of two users using the same password and getting the same salt is low. (And if you have so many duplicate passwords that it's a real concern, something is effed.)

    That's a salted red herring though, because all a salt can do is protect against pre-computed mappings between password input and bcrypt output. It doesn't actually decrease the likelihood that any given input password will inadvertently match some other input password's stored bcrypt result.

    It's easy to see this if you take the thing to an extreme: consider pissweakcrypt, a bcrypt-alike that uses the input password plus salt to encrypt an initial value that's 1 bit long rather than 192. Feed pissweakcrypt a strong passphrase and 128 bits of pseudorandom salt, and store the resulting 129-bit value in your database. Now here's the thing: you don't have 129 bits of collision resistance for input passwords, because 128 bits of what you have is just salt; it gets fed back into pissweakcrypt whenever you need to check an input password against the stored value, and you end up with a 50% chance of matching on any input password.

    You could use a truncated SHA-512 instead of SHA-256 for a pre-hash if always handing bcrypt its longest allowable input makes you happy, but from a security perspective you gain nothing by doing so. No more than 192 bits of the input password's entropy can ever emerge from bcrypt, so a randomly generated 448-bit input doesn't actually get you any more false-positive protection than a randomly generated 256-bit input would. Which totally doesn't matter, because even a 192-bit search space is so astronomical that you're never going to see an input password -> bcrypt result collision for any given salt value.

    Looking at it another way: if any part of your database design relies on UUIDs, you should be literally billions of times less worried about bcrypt collisions, and billions of billions of times less worried about SHA-256 collisions, than you are about the UUID collisions you already have no reason to worry about.



  • @morbiuswilters said:

    @HardwareGeek said:
    @Buttembly Coder said:
    putting two results into one through XOR or most (any?) bitwise or similar operation is lossy in terms of entropy, and makes it more likely that a random guess would generate a match. I am quite bad at explaining this.
    May I try? Thank you.

    Let's say hashing the first part of the input produces some result A, and hashing the second part produces result B. Let's say, for the sake of simplicity, that it's a really good algorithm, and there is only one input that can produce any given output. If you XOR A and B to get C, there are a whole bunch of A and B that satisfy A XOR B == C. Now there are a whole bunch of inputs that can generate a match on the result. Actually, the more bits in C, the more possible matches there are.

    Although that probably doesn't matter for password-hashing. What worries me more--and bear with me, because it's been many years since I looked at the internals of bcrypt--is that the way bcrypt works is it more-or-less uses the password itself as a key for a block cipher (hence the 55b limit.) So you'd be taking the output, xoring it with the next part of the password and then feeding that back in as a new key. That makes me really nervous.

    I think there is no problem if there are many inputs longer than 55 bytes that will match to the same output. There are no pairs of inputs SHORTER than 55 bytes that will match to the same output. Plus it does take into account the information that is longer than its limit, so nobody can complain "When I put a '1' on the end of my impossibly-long password, it still works?" Just because you can carefully craft a longer password doesn't mean that it's any less secure than the short passwords. (In the XOR case, you could add pairs of 0xFF, but only after you know the short password, and who has that key on their keyboard?)



  • @flabdablet said:

    It doesn't actually decrease the likelihood that any given input password will inadvertently match some other input password's stored bcrypt result.

    No, but that's not the point. It's to guarantee the same password hashes to multiple different outputs, as you said, to protect against pre-computation attacks. Salting doesn't exist to prevent two different passwords from having the same hash, that's what a well-designed crypto algorithm is for.

    @flabdablet said:

    It's easy to see this if you take the thing to an extreme: consider pissweakcrypt, a bcrypt-alike that uses the input password plus salt to encrypt an initial value that's 1 bit long rather than 192. Feed pissweakcrypt a strong passphrase and 128 bits of pseudorandom salt, and store the resulting 129-bit value in your database. Now here's the thing: you don't have 129 bits of collision resistance for input passwords, because 128 bits of what you have is just salt; it gets fed back into pissweakcrypt whenever you need to check an input password against the stored value, and you end up with a 50% chance of matching on any input password.

    I think we're talking at cross-purposes here. I was making the comment about salting because you said passwords should line up with SHA-256 should line up with bcrypt hashes. Assuming your algo doesn't totally suck, collisions aren't much of a concern in password hashing. Even if you have one, it would be nearly impossible to deliberately create one. And the primary purpose of password hashing is to protect users if the password database is leaked, since many users use the same password everywhere. If collisions were the primary concern, we wouldn't hash at all because then we'd never get a collision.

    @flabdablet said:

    You could use a truncated SHA-512 instead of SHA-256 for a pre-hash if always handing bcrypt its longest allowable input makes you happy, but from a security perspective you gain nothing by doing so. No more than 192 bits of the input password's entropy can ever emerge from bcrypt, so a randomly generated 448-bit input doesn't actually get you any more false-positive protection than a randomly generated 256-bit input would. Which totally doesn't matter, because even a 192-bit search space is so astronomical that you're never going to see an input password -> bcrypt result collision for any given salt value.

    You're absolutely right that 512 offers no more entropy than 256. And from a practical standpoint, either one is quite sufficient (although my preferred method would be not hashing at all and just making the user use a password less than 56 bytes.) However, theoretically, 512 would give you more protection. Once again, taking into account the primary attack vector here is someone with access to hashed passwords who wants to find the original passwords, and not someone trying to create collisions which wouldn't do you much good here, then one of the biggest possible vulnerabilities would be if someone found a known-plaintext attack against the bcrypt algorithm which allowed someone to partially recover the key.

    Let's say recovery cuts the entropy of the key in half. In that case, the worst situation would be if you were using straight bcrypt. If someone has a 10 character, completely random alphanumeric password (which would be quite secure) it's now reduced to 5 characters, which is substantially weaker. If you used SHA-256, the recovered key would be the 256-bit hash, which still would require you to reverse the SHA-256 hash to get the original key. However, you are helped a bit by knowing 128 bits of the hash. However, SHA-512 would provide even a little more protection because you'd only ever have 220 bits of the 512 bit hash.

    Once again, this is academic. It's so low on my list of concerns I wouldn't even bother recommending you SHA your passwords before bcrypting.



  • @morbiuswilters said:

    I think we're talking at cross-purposes here. I was making the comment about salting because you said passwords should line up with SHA-256 should line up with bcrypt hashes.

    And for any given salt value, that's true. So, given that the only possible way running a user's password through a pre-hash before passing it on to bcrypt could possibly reduce security is by destroying entropy, and given that bcrypt's own maximum output entropy is 64 bits less than that of SHA-256: a SHA-256 step before bcrypt is indeed completely harmless to security and a perfectly appropriate way to remove bcrypt's password length limit should that be required. It's certainly better (and easier!) than playing ad-hoc games with xor.

    @morbiuswilters said:

    Once again, taking into account the primary attack vector here is someone with access to hashed passwords who wants to find the original passwords, and not someone trying to create collisions which wouldn't do you much good here, then one of the biggest possible vulnerabilities would be if someone found a known-plaintext attack against the bcrypt algorithm which allowed someone to partially recover the key.

    Let's say recovery cuts the entropy of the key in half. In that case, the worst situation would be if you were using straight bcrypt. If someone has a 10 character, completely random alphanumeric password (which would be quite secure) it's now reduced to 5 characters, which is substantially weaker. If you used SHA-256, the recovered key would be the 256-bit hash, which still would require you to reverse the SHA-256 hash to get the original key. However, you are helped a bit by knowing 128 bits of the hash. However, SHA-512 would provide even a little more protection because you'd only ever have 220 bits of the 512 bit hash.

    In brute-force search of the SHA hashes of low- to moderate-entropy passwords, a hash that matched the recovered bits would be overwhelmingly likely to match all of them. Whether the SHA concerned is 256 or 512 bits would not change that, and both are computationally cheap enough (especially in an age where bitcoin miner ASICs exist) that the added cost of a SHA step to any brute-force search could be made insignificant.

    Using a SHA pre-hash step in order to remove a length limit that may annoy some users: fine and dandy. Using it because you think bcrypt might not be good enough on its own: cargo cult security theatre.

    Are we in heated agreement yet?


  • Discourse touched me in a no-no place

    @flabdablet said:

    cargo cult security theatre
    I like your phrasing!



  • Just as an update to this (Now you've all finished discussing ways of extending the number of bytes for bcrypt... personally, I prefer scrypt. Discuss :)

    I got my username in the mail and you bet, the password failed. I converted it to upper case (something I shouldn't have to do) and it failed again and told me my account was now locked.

    So I attempted to reset my password. It asked for my email, memorable information I typed on the application form, etc, and then told me that resetting the password isn't possible on a locked account and I needed to talk to customer services.

    I think I will talk to them, but not to unlock the account, to close the account! I've not used it yet but it's already driving me up the wall!



  • @Mole said:

    personally, I prefer scrypt. Discuss :)

    Personally, I prefer to make sure all my passwords are unique, machine-generated, and random with at least 100 bits of entropy. Then I don't have to give a shit whether the backend uses scrypt or bcrypt or even a single round of SHA without salt - even if the guy who stole the backend's password hash database has an ASIC brute-force password searcher, it's not going to find mine.

    I would also not choose to do business with any bank that refuses to let me use such a password.



  • @flabdablet said:

    @Mole said:
    personally, I prefer scrypt. Discuss :)

    Personally, I prefer to make sure all my passwords are unique, machine-generated, and random with at least 100 bits of entropy. Then I don't have to give a shit whether the backend uses scrypt or bcrypt or even a single round of SHA without salt - even if the guy who stole the backend's password hash database has an ASIC brute-force password searcher, it's not going to find mine.

    I would also not choose to do business with any bank that refuses to let me use such a password.

    I think it's pretty safe to assume that if someone has access to your password's hash, they also have the ability to change what is stored as that hash. The great thing about unique, machine-generated passwords is that it's trivial to generate a new one and even if a site stores passwords as plain text accessible from the user list, none of your other accounts lose any security.

    People should only ever know one password - the current password for their password manager.


  • Discourse touched me in a no-no place

    @Ben L. said:

    I think it's pretty safe to assume that if someone has access to your password's hash, they also have the ability to change what is stored as that hash.
    It's not safe to assume that read-only access is automatically trivial to elevate to write access. If it was, there'd be no need to try encrypting passwords at all (except for the phenomenon of people using the same password for many sites).


Log in to reply