# Password authentication over an insecure connection

I was thinking a way to send password to server secure way without using secure connection,I found one solution.I want to find flaw in this.(Note: I am begginer,dont judge me, I know little about cryptography and little about networks)

So server contains hashed version of my password. When i want to send password I send server request to generate me random key(big enough it is less likely to be same ). Then I hash password and add that hash to key and hash it again.I send that final hash to server. Server use key and hash the hashed password from database the same way and compare my hash with it.If it is the same,password is correct.

Ex. (Simplified) I want to send password "test123" to server. I request random key and server sends me key "999". I hash "test123" and get lets say "abc" ,and hash "abc999" and get "efg" and send that to server. Server recieves my "efg" , then gets "abc" hashed password from database, adds key "999" and gets "efg" ,so "efg"=="efg" ,password correct.

The someone listening the connection can't use the same hash because it will get different key.

First, note that a way to perform password authentication, or any kind of user authentication, over a connection is only useful if you assume that the attacker can see the data exchanged over the connection, but not modify the data. If the attacker is a man-in-the-middle who can suppress data between the client and the server or send packets that the legitimate parties will accept, then this is pointless. A man-in-the-middle can wait until the client has authenticated to the server, and then hijack the connection.

Establishing a secure connection is a solved problem as long as the client can verify that it's connecting to the right server. So user authentication over an insecure connection is not an interesting problem to solve. However, user authentication over a secure connection (i.e. no third party can see or modify the data) to an untrusted server is an interesting problem. Let's see how your protocol performs in this scenario.

So server contains hashed version of my password.

You're assuming that the server knows $H(P)$ where $H$ is a hash function and $P$ is the password. Actually, what the server knows is $PH(S,P)$ where $PH$ is a password hashing function and $S$ is a salt — see How to securely hash passwords for an explanation. You can fix this by having the server send the salt to the client, but that weakens the security of the system because it means that the salt is public — anyone can start a client connection to obtain the hash for an account.

When i want to send password I send server request to generate me random key(big enough it is less likely to be same ). Then I hash password and add that hash to key and hash it again.

That's not a key, but as a nonce. But ok, that's just a matter of terminology. The server sends a nonce $N$ and the salt $S$, and the client calculates $H(N || PH(S,P))$ ($||$ is concatenation).

I send that final hash to server. Server use key and hash the hashed password from database the same way and compare my hash with it.If it is the same,password is correct.

The server receives $H(N || PH(S, P_c))$ where $P_c$ is the password used by the client. It knows $N$ and $PH(S, P_g)$ where $P_s$ is the genuine password. It is indeed the case that $H(N || PH(S, P_c))$ = $H(N || PH(S, P_s))$ if and only if $P_c = P_s$ with overwhelming probability, assuming that $H$ is a cryptographic hashing function. So your scheme works.

However, there's a second flaw (in addition to having to publish the hash), and this one is devastating. Suppose that an adversary manages to obtain the copy of the hashed password on the server. Breaching password databases is a common attack, so it's very important to defend against it. The adversary doesn't know $P_s$ but they know $PH(S, P_s)$. Then they can straightforwardly calculate $H(N || PH(S, P_s))$, and impersonate the user.

In a nutshell, you've changed the protocol from requiring the client to know the password, to requiring the client to know the hash of the password. So the hash has become the password! This completely defeats the point of hashing passwords.

More generally, suppose you want a user authentication scheme where the client doesn't have to send the password to the server, but only some proof of possession of the password from which the password cannot be reconstructed. This either requires the server to know the password so that they can make the same calculations as the client, or else it requires using some method for not-knowing the password that isn't a hash.

There are methods that allow a client to know some secret value (the “password”) and to use it to authenticate to a server without requiring the server to know this secret value. They involve mathematical functions that have different properties compared to hashes. The most straightforward is public-key authentication: the client knows a private key, and the server knows the corresponding public key. The client signs a message using the private key, containing a nonce generated by the server. When the server receives the signed message, it can verify that the signature is genuine, using only the public key.

If you don't use a secure connection, it is vulnerable to man-in-the-middle attacks, so not secure.

If you do use a secure connection, then it is no better than sending the password directly.

• It's worth than that, actually. Depending on how you interpret the question (the algorithm description and the example are different), either the password serves as a hash, or the server needs to calculate the password from the hash. – Gilles 'SO- stop being evil' Jun 25 '18 at 6:36