Change PostgreSQL password encryption from MD5 to SHA - postgresql

Is there a way to change the PostgreSQL password encryption method from MD5 to SHA?
If Yes, can you please tell me how?
I am using PostgreSQL 9.5

Pg 10
With PostgreSQL 10, you can set password_encryption to scram-sha-256. From the docs
When a password is specified in CREATE ROLE or ALTER ROLE without writing either ENCRYPTED or UNENCRYPTED, this parameter determines whether the password is to be encrypted. The default value is md5, which stores the password as an MD5 hash. Setting this to plain stores it in plaintext. on and off are also accepted, as aliases for md5 and plain, respectively. Setting this parameter to scram-sha-256 will encrypt the password with SCRAM-SHA-256.
See this post for information about iterations using scram-sha-256
Pg 9.x
This can not be done without actually modifying the source.

Related

with scram-sha-256 is password encrypted during authentication

With the scram-sha-256 protocol, does Postgres server encrypt the client's password when initializing the connection so that authentication is secure and the password cannot be read?
It is even better than encrypted, it is salted and hashed. Not only can an eavesdropper not readily reverse it back to the raw password, the server can't either. A weakness though is that if you connect to a malicious server, it can simply insist on not using scram, and the default client will silently comply.

pgbouncer and scram-sha-256 setup

I was able to get SCRAM-SHA-256 authentication to work with pgpool, but I haven't been able to find a good example how to set this up in pgbouncer. I'm trying to use auth_query. In postgres, the user that pgbouncer will connect as has the password encrypted and stored in SCRAM-SHA-256. But I don't know how to create the entries in userlist.txt. This is supposed to be the format:
SCRAM-SHA-256$<iterations>:<salt>$<storedkey>:<serverkey>
What exactly are the storedkey and serverkey and how do I generate those? Which tools can I use to create this? In pgpool, I can use pg_enc but I don't see anything for pgbouncer.
You don't construct the SCRAM hashed password yourself, you get it by querying the pg_authid table in the PostgreSQL database:
SELECT rolpassword
FROM pg_authid
WHERE rolname = 'pgbouncer';
However, as the documentation says:
The passwords or secrets stored in the authentication file serve two purposes. First, they are used to verify the passwords of incoming client connections, if a password-based authentication method is configured. Second, they are used as the passwords for outgoing connections to the backend server, if the backend server requires password-based authentication (unless the password is specified directly in the database's connection string). The latter works if the password is stored in plain text or MD5-hashed. SCRAM secrets can only be used for logging into a server if the client authentication also uses SCRAM, the PgBouncer database definition does not specify a user name, and the SCRAM secrets are identical in PgBouncer and the PostgreSQL server (same salt and iterations, not merely the same password). This is due to an inherent security property of SCRAM: The stored SCRAM secret cannot by itself be used for deriving login credentials.
So if that user is used as auth_user, you cannot use a SCRAM hashed password for that user, but you have to use the clear text password.

Postgres unencrypted keyword is no longer supported

When executing this postgres command:
EXECUTE 'CREATE USER myuser WITH UNENCRYPTED PASSWORD ''my+password''';
I see the error:
RoundhousE encountered an error.
Npgsql.PostgresException (0x80004005): 0A000: UNENCRYPTED PASSWORD is no longer supported
Is there a workaround for this, or will the password need to be manually encrypted and supplied without the UNENCRYPTED keyword?
No. All you have to do is to omit the UNENCRYPTED.
You can supply both encrypted and unencrypted passwords that way, and PostgreSQL can tell the difference automatically.
PostgreSQL 10+ no longer support user creation with UNENCRYPTED password,
create it with ENCRYPTED:
CREATE USER myuser WITH ENCRYPTED PASSWORD ''my+password''

Set postgres password with hash

I need to clone role from one postgresql database to another. Is it possible to somehow extract role password hash and set it in another database ? I'd like to avoid any clear password manipulation...
If PostgreSQL thinks you're setting the password with an MD5 hash, it stores it directly. From the docs
If the presented password string is already in MD5-encrypted format, then it is stored encrypted as-is, regardless of whether ENCRYPTED or UNENCRYPTED is specified (since the system cannot decrypt the specified encrypted password string). This allows reloading of encrypted passwords during dump/restore.
you can select password from pg_shadow and use it as per docs, as Eavn told. Or you can use pg_dumpall -g which will basically prepare statements to run with md5 passwords eg. at my machine:
CREATE ROLE r;
ALTER ROLE r WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB LOGIN NOREPLICATION NOBYPASSRLS PASSWORD 'md5514f1b439f404f86f77090fa9edc96ce';

PostgreSQL multiple authentication methods

How can I set up multiple authentication methods for the same host/database/user rule? I want to be able to log in to my postgres user using both sudo -u postgres psql -U postgres (without having to enter a PostgreSQL password) and psql -U postgres --password. Something like the following in pg_hba.conf:
local all postgres md5
local all postgres peer
I can only get one method or the other working at the same time.
Thanks.
(I am using PostgreSQL 9.1).
Nope. Only one auth method is supported for any given configuration.
I'd love it if Pg could support fall-back authentication, where if an ident check fails it allows md5 auth instead. It doesn't support this at the moment, though, and I suspect (I haven't verified) that a protocol change would be required to support it.
What you can do is store the password in a $HOME/.pgpass file for the postgres system user. Give it mode 0600 so it's only readable by the postgres user and by root, both of whom can get direct access to the database files and configuration anyway. That way you get easy admin and md5 auth. On some systems you may have to set and create a home directory for the postgres user before you can do this. See getent passwd postgres to see if if the postgres user has a homedir and if so, where it is.
(UPDATE: used to read $HOME/.psqlrc - which is useful, but .pgpass is suitable for password storage)