Hacker News new | ask | show | jobs
by simias 1990 days ago
Seems awfully complicated, slow and error-prone to use full blown RSA for this. Why not send a challenge token and hashing salt and ask the user to reply with the (effectively one type password) crypto_hash(crypto_hash(salt, password) + token)?

On the backend they already have crypto_hash(salt, password), they know the token they sent so they can build the same hash and see if it matches. This way the backend actually never has access to the non-hashed password.

The only inconvenient I can see is that you can't transparently rehash on login on the backend if you decide to migrate to a different, potentially stronger hash algorithm later. But then again if the worry is that passwords could leak in the backend, using hashes makes it effectively impossible by construction.

I guess nobody gets fired for using RSA. But at the same time doing "serious" crypto in JS always feels icky to me.

2 comments

That kind of construction involves storing whatever is required for login in plaintext on the backend side. You can get around that limitation by using something like SRP, but that is even more complex than using RSA. On the other hand SRP-like construction would have real security benefits while passing RSA encrypted password over the same channel you got the public key (and implementation of the whole thing) from is of somewhat questionable benefit.
I have wondered many times why we still send the password over the wire (even if in SSL). It should be hashed with a salt every time before being sent! A lot of people reuse their passwords, the user shouldn't trust the website to hash it.
Because calculating the salted hash on the client side will just substitute the hash for password and render the whole hashing useless. Also it would require additional roundtrip to server in order to get the stored salt.

Then there is the UX problem where mechanism like that would have to be implemented on the browser level (and in fact it is as Authorization: digest is mostly what you are proposing) which according to some leads to “ugly and confusing” UI.

> Because calculating the salted hash on the client side will just substitute the hash for password and render the whole hashing useless.

I don't understand what you mean. Just in case I didn't make myself clear, I don't mean substituting the hashing on the server, I mean adding it on the client.

> Also it would require additional roundtrip to server in order to get the stored salt.

It could be salted with some constant/domain name.

> Then there is the UX problem where mechanism like that would have to be implemented on the browser level

What I am saying could perfectly be done with javascript, although I don't see why browsers could not integrate it too.

> which according to some leads to “ugly and confusing” UI.

I am completely lost, I am not sure if you understood me but I don't understand what you mean. Can you explain yourself further or provide a resource that explains this UX problem you're talking about?

The first two points have to do with the fact that if you do the whole process only with symmetric primitives you are only spliting the traditional salted hash into two computations one of which then becomes essentially redundant. If client uses deterministic salt, then whatever you send over the wire is equivalent to password and constant for every authentication. If server sends random challenge which is then hashed by client together with something derived from users password then whatever value that is stored on server in order to check validity of the response is sufficient to fake the response (and also essentially equivalent to plaintext password as it has to be derived from it in some deterministic manner independent of the random salt/challenge). That is to say, the protocol has to be somewhat more complex than that and involve asymetric cryptography to solve both of these issues at once.

There is no technical reason why this could not be implemented in pure JS (and there is lot of things that do something like that with varying complexity and security properties). But there is the question of exactly what is the threat model where the server is trusted to provide implementation of code that defends against compromise of that exact same server.

And as for the UX/UI issue of browser-based security: for security features like this to be truly secure the user has to be sure that he is interacting with the native browser/OS UI and not with something that can be intercepted by JS (or some other untrusted code). This is the reason why various parts of browser UI cannot be hidden, why legitimate permission popups overlap browser toolbar and the idea behind Ctrl-Alt-Del in Windows NT. Such UI by design cannot look as part of your website/application which both confuses even technical users and annoys marketing people because of added friction.

Also what didn't help adoption of any kind of more secure authentication for public facing websites is that in IE the resulting UI was ugly, inconvenient and in some cases downright broken (eg. dialog box used to confirm that you really wanted to use certificate from PKCS#11 token not only didn't say what for, it didn't say anything except “Error! Yes/No”).

> If client uses deterministic salt, then whatever you send over the wire is equivalent to password and constant for every authentication. If server sends random challenge which is then hashed by client together with something derived from users password then whatever value that is stored on server in order to check validity of the response is sufficient to fake the response (and also essentially equivalent to plaintext password as it has to be derived from it in some deterministic manner independent of the random salt/challenge)

You seem to misunderstand the purpose of what I am proposing. I am not proposing this scheme as an alternative to what's proposed in the blogpost.

I am proposing this procedure as an extra protection step for password reuse. If you were to run an exploit on the server that reads its memory contents, you may find a user "Admin" that uses the password "FavoriteFood-DateOfBirth".

If you sent the original version of that password, then such an attacker will find real-world information about you. That information can be used to exploit your identity on other websites. If the password is hashed, then that information doesn't get leaked. Sure, you can fake your authentication to this server, but you have not gained real-world information about your target.

Without salt, the attacker can fake the authentication on every service where that password gets reused. But with salt, every server sees a completely different password on their end. Essentially, your hashed password with salt has become your new password in the server's eyes.

> : for security features like this to be truly secure the user has to be sure that he is interacting with the native browser/OS UI and not with something that can be intercepted by JS

Yes, you were one step further than me on this front. I do agree that communicating this to the user is non-trivial.

>Because calculating the salted hash on the client side will just substitute the hash for password and render the whole hashing useless.

It would help in the case of reused passwords, which is still rampant in my experience.