2

In usual scenarios, the connection string contains the password in plain text, but this can be captured by Wireshark, so I want to use the encrypted password in a connection string. I found the below excerpt from the Postgres documentation:

Encrypting Passwords Across A Network The MD5 authentication method double-encrypts the password on the client before sending it to the server. It first MD5-encrypts it based on the user name, and then encrypts it based on a random salt sent by the server when the database connection was made. It is this double-encrypted value that is sent over the network to the server. Double-encryption not only prevents the password from being discovered, but it also prevents another connection from using the same encrypted password to connect to the database server at a later time.

If I understood it correctly, to get the salt, I need to connect to the database, but doean't that mean that the password can be spoofed?

I tried to google around but did not found a satisfying solution. I want to understand how can I get the random salt from PostgreSQL server using java and then encrypt the plain password with it and use an encrypted password to establish a connection.

2
  • 1
    You connect to server, before sending any login information the server sends you the salt, then you login with a hashed password. The client library you use should handle this, not you. Commented Mar 21, 2019 at 11:09
  • @SamiKuhmonen you mean the postgresql driver inherently supports this. I do not have to do any additional changes other than calling usual getConnection? Commented Mar 21, 2019 at 12:49

1 Answer 1

5

If you, user arvind, set the password to secret, the actual password is set to

'md5' || md5('secret' || 'arvind')

that is md50624d6c2e831004efb7f4173699a1775. That's what you'll find in the pg_authid system catalog.

Now the establishment of a connection works like this:

client to server: I want to connect to database mydb as user arvind.

server to client: Ok, I want MD5 authentication. Your salt is g73j.

The client has been given secret as password.

First, it uses the formula above to get the real password (first hashing).

Then, the client hashes the password a second time using

'md5' || md5('0624d6c2e831004efb7f4173699a1775' || 'g73j')

client to server: the hashed password is md573ae1f550fb4bcd28411cefb24b800bc.

The server calculates the same hash and compares the result to what it got from the client.

If that is the same, the server knows that the client must have the real password, otherwise it couldn't have calculated the correct hash.

The password itself is not transferred, so it cannot be stolen by an eavesdropper.

server to client: Ok, you're in.

The actual messages look different of course, but that's all in the documentation.

Sign up to request clarification or add additional context in comments.

4 Comments

is there any configuration needed for enabling MD5 authentication on the server side, or is it the default behavior? And if I understood correctly, this is happening behind the scenes, right?
You need to specify md5 in pg_hba.conf for authentication to work like that. If you use a client library, the library will do that for you. If you want to speak to the server directly via network, you'll have to implement that yourself.
does all the postgresql versions support double-MD5-hashed password ? According to my research, postgresql 9.4 or above supports this.
Every version since the dawn of time has supported this.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.