Hashing Passwords for a Web Login

I just found this article in which Paul talks about hashing passwords: https://blog.xojo.com/2015/10/09/tips-dealing-with-the-problem-of-passwords/

It’s critical message is:

I agree with that. In fact, I am worried about implementing this. Because, despite the fact that the blog article is tagged with the “Web” keyword, it does not address the problem with using this in a Web project:

In a Web project, the password needs to be hashed BEFORE it gets sent over the network to the Xojo app! Otherwise, the password, if not using SSL, could be easily compromized. And even with https it still violates the quoted rule, because now, the app knows the password, at least temporarily, although it should not need to. I.e, if the server got hacked, someone could then log every password that’s sent to the app.

So, what we need here is a way to hash the password in the frontend, with some Javascript.

Has someone solved this already?

The password should be hashed on the server side, and communication should be via https. If the latter is not possible, perhaps you could supply a public key to the web side that can be used to encrypt the password before transmission.

@Thomas Tempelmann — Isn’t it possible to use some JavaScript to hash the password before sending it? (it may be a naive question)

I think that’s what Thomas is trying to get at. He would like to do it browser side prior to transmission, and is asking if anyone has already implemented anything.

If someone points to a js library that does this securely and correctly, I’m sure one of the web experts can wrap it up. If it’s super easy I might even have time to.

Kem, you ignored my reason: Even with https, I do not want to transmit the actual password to the server because it could still be grabbed there. It’s a security measure against hacks.

Tim & Stphane - the part that I don’t know how to solve yet is how I would intercept the entered password from being transmitted to the server as I do not understand how Xojo’s frontend transmits inputs in general.

Does it, for instance, in order to keep things snappy, always transmit the input field contents along with related events, or only when the app requests a specific input value?

Also while typing in a password, I assume the frontend sends the keystrokes to my app, which would already be a problem. So I need to prevent that, too, but only for the password field. But maybe, when I do not implement the Keydown event, the frontend is optimized not to send the keystrokes? That’s the kind of questions I’m worried about.

Crap, I didn’t consider that. It could be made a custom control that is a text field, but then you’d lose the IDE designer aspect.

This “not considered” is the part that scares me. I don’t know what gets transmitted even though I like to keep it secret. For instance, initially I had thought I could just not use https and simply encrypt the password, because apart from that, the data I send to and from the server is not really secret, so I would not need SSL for that. But the fact that even typing, and maybe other things I have not realized yet, might already spill the secret password over the net is problematic.

@Thomas Tempelmann — Now I see, and I agree with you: Xojo should be clear on that topic!

Typically, it is not recommended to do the hashing on the client, because that makes the hash password-equivalent. If somebody managed to obtained the hashed password, they only need to submit it to the server as-is to authenticate. Big no-no. So the way described in the blog post is the recommended way to do it. Yes, the server has the password for a short amount of time, but that’s no different than entering your credit card details onto a page anyway.

Also, TLS/SSL isn’t just about protecting the user’s private data. It’s also to protect the data you are delivering to the client. It defends your stream against data being injected by the ISP, for example, a “hey you didn’t pay your bill” message that might otherwise mess up your app. An unencrypted connection also means your code could be modified to never encrypt, or redirect your login request to another server.

https://doesmysiteneedhttps.com

Thom, you seem to assume I didn’t do my homework :slight_smile: I would, of course, use a nonce, passed from the server, to prevent replay attacks.

But you can’t compare that to the hashed password on your server. You’d end up hashing the hash. Something like Hash = SHA512(SHA512(password) + nonce) - substituting SHA512 for the actual algorithm of course - which basically just makes the hash into the user’s password.

Don’t try to outsmart security standards. I’ve been down that road. What seems smart now is likely to become something you smack your forehead over later. Everybody does it this way for a reason.

Thom, that’s not what I’d be doing.
This is what I would be doing, which is a proven and often used concept: https://stackoverflow.com/a/24978909/43615
Or am I getting that wrong?

The only problem I see here is that doing client-side hashing will reduce the amount of PBKDF2 iterations because the client is probably not as fast, especially if it’s done in JS. So, the key needs to be longer to compensate for that.

What scares me more is that I hadn’t even HEARD of nonce before. Had to look it up on Wikipedia https://en.m.wikipedia.org/wiki/Cryptographic_nonce

Maybe someone could make a list of what the “homework” actually is?

1 Like

I know Challenge Response. I think you missed a critical piece there:

Challenge Response is definitely less secure than using PBKDF2 or bcrypt.

Thom, what you quote refers to the algo the Question mentions. The answer I link to solves that.

I agree with you on the need for bcrypt or PBKDF2, though. That’s why I mentioned it above.

Just quote the answer - it’s annoying when everyone has to click the link to get it:

“This protocol is basically a challenge–response authentication. It is used to avoid sending the actual secret (e. g., password), but the response can only be valid with knowledge of the secret. And to avoid replay attacks, a nonce is incorporated.

However, the mentioned protocol requires the server to store the secret in a retrievable form (e. g., plaintext or encrypted).

But you could change the protocol to allow the use of password hashes instead of the plaintext passwords by requiring the client to generate the same password hash:

Client requests salt and nonce for user-inputted username from server.

Server retrieves salt from its database, presumably via username, and responds with salt and nonce (i.e., hereafter referred to as server nonce).”

Client uses salt and user-inputted password to generate a password hash and uses the password hash, the server nonce, and its own client nonce to generate a nonce hash.

Client sends user-inputted username, client nonce, and nonce hash to server.

Server retrieves both server nonce and user password hash from its database, presumably via username.

Server combines server nonce, client nonce and password hash to generate a nonce hash.

Server compares nonce hash just generated with nonce hash sent from client.

If the hashes match, client is authenticated. If not, client is rejected.

[quote=436806:@Thomas Tempelmann]Thom, what you quote refers to the algo the Question mentions. The answer I link to solves that.

I agree with you on the need for bcrypt or PBKDF2, though. That’s why I mentioned it above.[/quote]
Yeah but my point is you’re not improving anything, you’re just manipulating the user’s password.

Markus, you just posted the content of the linked SO answer as your own text?! At least turn it into a quote.

Thom, I am just trying to work on the goal I stated at first, i.e. to prevent the password from leaving the frontend. Because that’s a security flaw inherent to Xojo Web.

Using the linked method will solve this, won’t it? I would still perform another PBKDF2 based hash on the server to better secure it there, but don’t you think that doing the frontend hashing deals better with the case of a compromised server, because then the attacker can’t grab all the passwords that the user would otherwise send for their logins?

After all, I need to consider break-ins. Otherwise, why even bother salting and hashing the passwords on the server? The purpose of hashing is to prevent that someone who gets access to the server can look at all the users’ passwords and use them on other sites, for instance, where the users might use the same pws, or to use them to access other data stored on the server. Agreed?