1
$\begingroup$

My rudimentary understanding of HTTPS and the Diffie-Hellman key exchange is that the client and server can establish a secured connection by generating the same key based on their private secrets and shared secret. That key is then used to encrypt/decrypt the data being passed back and forth between the two parties.

This means that I have established a secure connection, but says nothing about the identity of the client connecting to my server. It could be anyone with a browser. My question is, in order to identify a client after already having established an encrypted connection, is it safe to establish the user's identity by sending a username and hashed password over said connection? Is this a sort of standard procedure?

In most of my use cases, my client and server are going to be either NodeJS or Java applications that I have programmed, some running on the same machine and possibly on a different server in different locations, so I am not too concerned about creating any kind of system to allow users to sign up. Would a preset hashed password be secure enough, or should I use asymmetric keys like SSH? I'm just not totally sure what the pros/cons are or what the standard way to authenticate a client is. Do I even need to hash anything, or can I just have the user send a plaintext password and check it against my database since the connection is already encrypted anyway?

$\endgroup$

1 Answer 1

1
$\begingroup$

The most common way for web sites is to send the password itself to the server, which then uses a "password hashing function" (NOT a cryptographic hash) like Argon2id or bcrypt to create a digest (containing some settings, a unique per account salt, and the hash of the password), and then compares the digest to the value stored on the server for that user.

It's possible to do this twice: you can use a password hashing function on the client, then send the digest to the server, and then use another password hashing function on the full digest. This can be done with different settings for the work factor on the client and the server to reduce the workload the server needs to compute. The server should use a second salt, still unique per account. The big disadvantages of this are that most clients won't have code for a password hashing function, he per-account storage overhead is higher (need to store an extra digest, so probably about 64 bytes more per user), and the login process needs to send the client the work factor settings and one salt.

For some applications it's possible to have clients generate an asymmetric key pair, send the server the public portion, and then authenticate by signing a challenge the server sends. EG the server could send a 32-byte random value to the client, the client could sign it, and if the signature is valid for the stored public key the server grants access. SSH does this. Ed25519 SSH keys are small, and there's lots of support for SSH's format. The disadvantage is that users need to keep these keys stored, losing their private key means losing access, and leaking their private key allows attackers access (just like a password). If viable this is the most secure option.

There are also saPAKEs, like OPAQUE good article here, which don't require sending the server a copy of the password (or a hash of the password), but they're not standardized yet. I'd avoid these for now, but keep an eye out for them to become standardized. And do read that article, it describes common password use cases more thoroughly than I did here.

$\endgroup$
1
  • $\begingroup$ This is a really good answer and it cleared up a lot of uncertainty for me. And I don't care if I'm not supposed to use comments to say thanks, so...thanks! $\endgroup$
    – leisheng
    Commented Jan 30, 2021 at 7:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.