Sign up ×
Information Security Stack Exchange is a question and answer site for information security professionals. It's 100% free, no registration required.

According to Postgres's documentation, Postgres's password authentication method uses MD5 hashing to secure the password:

The password-based authentication methods are md5 and password. These methods operate similarly except for the way that the password is sent across the connection, namely MD5-hashed and clear-text respectively.

If you are at all concerned about password "sniffing" attacks then md5 is preferred. Plain password should always be avoided if possible. However, md5 cannot be used with the db_user_namespace feature. If the connection is protected by SSL encryption then password can be used safely (though SSL certificate authentication might be a better choice if one is depending on using SSL).

I've heard from numerous sources that the MD5 hashing algorithm is no longer considered secure. Does this mean that I should avoid using password-based authentication for Postgres? If so, which alternative method should I use?

share|improve this question

3 Answers 3

up vote 11 down vote accepted

If using SSL, then what PostgreSQL does is fine. If not using SSL, but still doing the authentication across the network, then what PostgreSQL does stinks. Their games with MD5 are worthless, but not because they use MD5. MD5 has its own issues, but there they are just misusing it awfully.

With "cleartext password" authentication, the client shows a user name and a password, and the server accepts them if they match what the server stored.

With "md5" authentication, the client shows a value (which happens to be the MD5 hash of the concatenation of the password and the user name) and the server accepts it if it matches what the server stored.

So you see it: in both cases, the client shows a bunch of bytes to the server, always the same sequence. It suffices for an attacker to tap on the network to observe these bytes, and then connect to the server and sends the same bytes to be granted entry. That the bytes are the result of a MD5 hash is completely irrelevant here. This MD5 hash is said to be password equivalent. As long as the connection can be eavesdropped at all (i.e. no SSL), then security goes down the drain.

See this page for the details of the MD5 computation. They call it "encryption", which it is not at all (hashing is not encryption).

We could even argue that using this MD5 decreases security: when a plaintext password is used, it can be forwarded to another authentication server (using Kerberos, LDAP,...) and that authentication server could then employ strong storage techniques (see password hashing). With the PostgreSQL-specific MD5 hash, this cannot apply. When the "md5" authentication method is used, it MUST be against a table in the database which contains all these "md5" value as is. An attacker who can get his hands on, say, a backup tape or an old disk, will immediately obtain many free accounts on the database.

And, I insist, nothing in all this has anything to do with MD5 cryptographic weaknesses. All of this would still apply if MD5 was replaced with SHA-512.

share|improve this answer
@Tom_Leek - could you revise your answer in light of the answer below and the use of random salt? To me it seems like it has the strength of challenge-response and is not susceptible to replay? – Konrads Aug 25 at 8:02
@Konrads, yes, it is not susceptible to replay when the md5 auth-method is used. Nevertheless, the problem with this method is it's the client-side hashing. The hash in the pg_shadow table is now a password equivalent. When an attackers steals this table (we assume this will happen eventually), she just uses any hash for authentication without even spending time to crack md5. – koddo Nov 2 at 16:40

Yes, using MD5 is safe. When a client wants to authenticate, the server sends a random salt value. The client uses that value, along with the password to generate a MD5 hash. Because a random salt is used, an attacker can not use a dictionary attack. Also, because the salt is changed each time a client authenticates, this is no ability to replay old authentication requests.

Details here in the AuthenticationMD5Password section.

share|improve this answer
Ah: "concat('md5', md5(concat(md5(concat(password, username)), random-salt)))" Yeah, that's definitely safer than the method Tom Leek assumed in his answer. I wonder though if the cryptographic weaknesses of MD5 might come into play here. Could MD5's weaker-than-expected preimage resistance be a problem for the security of this scheme? – Ajedi32 Aug 25 at 17:21
Also, while this scheme might preserve password secrecy in the event of a MITM, I'm guessing it won't protect the privacy or security of the connection itself, right? Or is that password used to encrypt the connection somehow? – Ajedi32 Aug 25 at 17:23
Also, it looks like Tom Leek's assertion that "An attacker who can get his hands on, say, a backup tape or an old disk, will immediately obtain many free accounts on the database." still applies here. Either md5(concat(password, username)) or password has to be stored in plaintext in the database somewhere in order for Postgres to authenticate the connection, and if the attacker gets his hands on either of those values he can use it to authenticate to the database. – Ajedi32 Aug 25 at 17:28
backup files should always be encrypted. And your production server should have the database on an encrypted drive. – Athir Nuaimi Aug 30 at 22:42
True, but encryption is just another layer of security. It's not an excuse for storing unhashed password-equivalents in your DB. – Ajedi32 Aug 30 at 22:46

TLDR. It can be secure if you configure it properly and use good long passwords.

1. In postgres the md5 auth-method means client-side hashing (discussions: 1, 2), which makes hashes password equivalent. A hash in the db is compared to a hash received from a client. An attacker can use any hash from stolen pg_shadow table directly, without even spending time to crack the md5.

It's much safer to assume the hashes will be stolen eventually and to avoid client-side hashing.

You can actually just take a look at the code, it's quite simple: <— direct link to this line:

 if (strcmp(crypt_client_pass, crypt_pwd) == 0)

See what happens when the port->hba->auth_method == uaMD5. Yes, one can't intercept a hash clear-text, it's again salted and hashed. But when stolen by any other attack, it can be used directly without cracking.

2. Unsurprisingly, you can use server-side md5 hashing with postgres by using the password auth-method and create user whatever with encrypted password.

These methods operate similarly except for the way that the password is sent across the connection, namely MD5-hashed and clear-text respectively.

Use SSL to protect the clear-text password. You probably should know the way its hash is stored — the salt is reused:

 /* Encrypt user-supplied password to match stored MD5 */
 if (!pg_md5_encrypt(client_pass,          // const char *passwd
                     port->user_name,      // const char *salt
                     crypt_client_pass))   // char *buf

One could even create random generated throwaway usernames to use them as salt, but I'm not sure if it's a good idea, this is error prone.

While the general recommendation is to migrate from md5, it's still not broken for password hashing. Relevant question: Why do people still use/recommend MD5 if it is cracked since 1996?

Don't use short passwords. Long, high-quality random passwords are still safe.

For a quick estimation, these (unfortunately, quite old) links have some numbers:

Update: thanks to RhodiumToad from #postgresql channel on for clarifying that md5 is still not broken for password hashing, good long passwords will save the day.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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