This is mostly a thought experiment for client/server communication, and I want to know the flaws.
When a user account is created (with U
as the username and P
as the password,) I generate a random salt (S
) and store these values in the database (on the server-side): U
, S
and H
which is computed as H = hash(U+S+P)
.
When authenticating a user:
- The client first "attempts an authentication" by sending
U
to the server. - The sever creates a challenge code (
R
) for that user and stores it in the database, along with the time this challenge would expire (T
) and sendsR
andS
back to the client. - The client calculates its own version of
H
(by hashingU
andS
andP
together; it hasU
andP
, and receivedS
from server.) - The client then computes a new value
G
asG = hash(H+R)
and sends thisG
back to the server (actual "authentication request".) - The server hashes its own
H
together withR
to reconstructG
and authenticates the user iff itsG
matches the value received from client andT
has not passed yet. - Whether authentication succeeds or fails,
R
is removed from the server database.
The flaws I'm already aware of are these:
- When creating an account, the password is transmitted in plaintext. This can be mitigated using a dedicated account-creation service that employs SSL for creating accounts.
- Attempting an authentication will result in some resources being allocated on the server. This can be mitigated by allowing only one (or a fixed number) of challenge codes per user.
- Trying to discover valid usernames and salts by generating many authentication attempts; which the server can foil by sending a random salt and challenge code even when the user does not exist.
Here are my specific questions:
- What am I missing? Where is the disaster waiting to happen?!
- What can I do to make this more secure/better? Other than using SSL and just sending plaintext passwords (plaintext only from the perspective of my application.)
- I'm thinking of SHA-256 for all hashes. Are there any flaws in the SHA-2 family? Is hashing the values once enough for generating
H
andG
? - For generating
H
andG
, are other permutations of values better? e.g.P+U+S
,R+H
, etc. - What conveniences am I denying my users? (Apart from their authentications now needing two round trips to the server.)
UPDATE: Ultimately, I want to do this:
After a successful authentication, the server generates a session key K
as: K = hash(H+F)
where F
is a random string. F
is sent to the user and K
is retained in the database. The client reconstructs K
using the received F
and encrypts all communications with the server henceforth with a symmetric cipher (e.g. AES) with K
as key.