3 ms·
Very valid questions. Let me try to answer them and let's see if those answers are valid or not. Yes, the scrypt hash just becomes the password for the server.
by sinatra 11y ago
Very valid questions. Let me try to answer them and let's see if those answers are valid or not.
Yes, the scrypt hash just becomes the password for the server. However, this password is going to be unique and almost impossible to guess. Salting this password on server side doesn't give us any additional benefits. The server can store the salt that the client used, though.
Yes, the MITM point was minor. Just another minor security benefit on top of TLS (which takes the majority of the burden of securing against it). So, maybe I shouldn't even mention this point.
- owenmarshall 11y ago>Yes, the scrypt hash just becomes the password for the server. However, this password is going to be unique and almost impossible to guess. Salting this password on server side doesn't give us any additional benefits. I don't even your threat model. Can you walk us through how you see this working? Client takes 'crappypassword' as input, sends p = scrypt('crappypassword') The server stores SHA256(p)? EDIT: misread what you said. is this correct?
- sinatra 11y agoYes, now it's correct.
- AstralStorm 11y agoAnd still invalid. Are you assuming that collisions against SHA256(bcrypt(p)) are harder than SHA256(p), right? Any math to prove that? Otherwise, you're relying on the user side to properly safeguard bcrypted password. That is often wrong. You cannot store any kind of transformed password anywhere, or it's no longer a password, but a token. Yes, those "Remember me" things transform passwords into tokens. Tokens can be stolen.
- timv 11y agoNote: I'm not endorsing the client-side scrypt/bcrypt approach, but I do think it's interesting. I'm going to refer to bcrypt because that's what your comment used, but the parent post used scrypt. > Are you assuming that collisions against SHA256(bcrypt(p)) are harder than SHA256(p), right? I don't think it is. I think it's assuming 2 things: 1. That SHA256 collisions are rare enough, and SHA256 attacks are hard enough, that they can be ignored. 2. That the output space of bcrypt is large enough to overcome the risk that salting is usually designed to overcome. On the first point: This approach simply isn't worried about SHA256 collisions between passwords. Yes, it's theoretically possible that 2 users with different passwords and/or different salts might end up with the same hash. If that happened often then it would be an issue - if you had n distinct users in your system but only n/2 distinct hash values, then if an attacker had a copy of your password store, it would effectively double the pay-out each time they successfully cracked a user's password (that is, each cracked password would allow them to authenticate as 2 users). But in practical terms, collisions are going to be tiny, and you're really worrying about the case where n distinct users have n-1 or n-2 distinct hashes. That's not going to meaningfully change your exposure. What is more of a risk (and this might be the point you were making) is that if any of your hashes happen to collide with the hash of a known input, then you're screwed, and while that's unlikely, "unlikely" isn't an ideal protection. When you're storing { SALT , HASH( SALT || INPUT) } you're reasonably protected against such collisions because they would only be effective if the known input happened to start with the salt. What the bcrypt approach can offer is that it knows that the input to SHA256 needs to be the output of bcrypt, so you can refuse to accept anything that isn't 186 bits long (or 31 base64 characters, depending on your approach). That constraint might well be stronger protection than a salt, although I haven't run any numbers. Probably adding a salt is safer, and I was going to attempt serious analysis on this scheme I'd certainly want to test whether that was true or not. On the second point, salting is usually designed to work around the scenario where 2 users have the same password and therefore (absent a salt) would have the same hash. It is not specifically intended for the scenario (described above) where two users have different passwords that happen to hash to the same thing. In the approach discussed here, the input to the hash is the output from bcrypt. That value has already had a salt applied, so 2 users with the same original passwords would be providing different inputs to our hash function, so we would be storing different outputs. > you're relying on the user side to properly safeguard bcrypted password I think that's a genuine issue. You need to do a not-insignificant level of client-side processing on the user's password. You're relying on the browser disposing of that data securely. It's "just bits in RAM", but bits in RAM leak, and there's no way for the browser to know that the bits you were working with were sensitive.
- deleted 11y ago[deleted]
- ddlatham 11y agoI think the simplest thing is for the server to generate a salt for every user and add a step for the client to request the salt for a given user. If you want to protect against account enumeration then you need to be able to generate consistent salts for accounts that don't exist also.