PG18 Hacktober: 31 Days of New Features : Secure Password Hashing with SHA-2 Algorithms

Welcome to the Security track of #PG18Hacktober

As part of the PG18 Hacktober: 31 Days of New Features blog series, we’re dedicating the next four posts to one of the most critical (yet sometimes overlooked) areas of database development: Security.

PostgreSQL 18 brings several quiet but powerful improvements in this space. Over the next four posts, we’ll explore new capabilities that help you protect data, strengthen authentication, and secure your PostgreSQL deployments like never before.

NB: We hope you’re able to take a look at our pg_upgrade features blogs, if not, here’re the links to blog1 and blog2

Today, we begin with a fundamental upgrade in password security: SHA-2 support in pgcrypto’s crypt() function.

Why SHA-2 Password Hashing Matters

Password security is fundamentally tied to strong, slow, and unpredictable hashes:

  • Old algorithms (like MD5) are fast and vulnerable to brute force/rainbow table attacks.
  • Modern adaptive hashes like sha256crypt and sha512crypt use many iterations and salts, making them slow and unique.
  • These are compatible with crypt(3) tools on modern Unix systems, making integration easier.

The new SHA-2 Support in pgcrypto

We all know that we use these two functions crypt() and gen_salt() for password hashing in pgcrypto extension. crypt() does the hashing and gen_salt() prepares algorithm parameters for it. PostgreSQL 18 introduces two modern, secure hash algorithms for passwords: sha256crypt and sha512crypt. These are implemented as part of the pgcrypto extension and follow the widely-recognized crypt(3) UNIX password format. The upgrade is simple but powerful—by using the new salt types, any application or developer working with the crypt() function can instantly benefit from state-of-the-art password security.

AlgorithmMax Password LengthAdaptive?Salt BitsOutput LengthDescription
sha256cryptunlimitedyesup to 3280Adapted from publicly available reference implementation SHA-crypt.txt
sha512cryptunlimitedyesup to 32123Adapted from publicly available reference implementation SHA-crypt.txt

These two algorithms, the iteration count ranges between 1000 to 999999999 (default = 5000).

How to implement

Let’s start with the gen_salt() to generate the random salt value for password hashing with both the algorithms.

#sha256crypt algorithm with default iterations
postgres=# select gen_salt('sha256crypt');
            gen_salt
---------------------------------
 $5$rounds=5000$xro9BI5vHFTeErM4
(1 row)

#sha256crypt algorithm with minimum iterations
postgres=# select gen_salt('sha256crypt',1000);
            gen_salt
---------------------------------
 $5$rounds=1000$nrfTQme2qUVCSB7C

#sha512crypt algorithm with default iterations
postgres=# select gen_salt('sha512crypt');
            gen_salt
---------------------------------
 $6$rounds=5000$/Txi1ZJiO8c4C65e
(1 row)

#sha512crypt algorithm with minimum iterations
postgres=# select gen_salt('sha512crypt',1000);
            gen_salt
---------------------------------
 $6$rounds=1000$EgT8uD6DC2e0UXxj
(1 row)

The gen_salt() gives the hashing algorithm $6$ , iteration count 1000 and the random salt value $EgT8uD6DC2e0UXxj . That’s why we called these algorithms as ‘adaptive’ as we can change the no. of iterations

Let’s check the crypt() function with these two algorithms

#With sha256crypt
postgres=# SELECT
  crypt('TestPassword', gen_salt('sha256crypt')) AS hash1,
  crypt('TestPassword', gen_salt('sha256crypt',1000)) AS hash2;
-[ RECORD 1 ]----------------------------------------------------------------------
hash1 | $5$rounds=5000$cUZXrvdik6w7PVgf$TBpT8JoxG24WgpPVyFKC1llgYhmukqs76R8VUfwQ2SC
hash2 | $5$rounds=1000$mPe7n/KSQMp6i3Gd$D.o9rccPTUF0gJysn.B71x0V1GERaL4IMhvktxXlXD1

#with sha512crypt
postgres=# SELECT
  crypt('TestPassword', gen_salt('sha512crypt')) AS hash1,
  crypt('TestPassword', gen_salt('sha512crypt',1000)) AS hash2;
-[ RECORD 1 ]-----------------------------------------------------------------------------------------------------------------
hash1 | $6$rounds=5000$kBfwH/jokldDal.B$OwjNDrjzXMIRUzEXzWxSYWOzQSNPVHoCHCVjraAoXZHU.a3vU38wjHTXZGXE8P5sp5Fb7rDLekMYN9cZQmh6e.
hash2 | $6$rounds=1000$HtA3A5.Cy7Y.0CMR$wY7M3r9s4sb1RVNgCGV9cbi3dfxSkA8ns4Y/5Yg2UT5ihZkA9zBD5ERKhQUSCnmKItEmDZcDQ7BsY5vqX4xxH1

PostgreSQL 18 allows you to choose and tune these modern adaptive hash algorithms for secure password storage and verification.SHA-512crypt provides a stronger hash than SHA-256crypt but at a moderate performance cost. Let’s see the performance

Algorithm vs round1000(Min)5000(Default)1000050000100000
sha256crypt0.653 ms3.492 ms6.698 ms37.918 ms82.520 ms
sha512crypt0.570 ms2.520 ms6.362 ms32.116 ms64.914 ms

The increase in no. of rounds(iterations) will makes the hashing take more time.

Summary

PostgreSQL 18 significantly enhances password security by introducing support for SHA-2 based adaptive hashing algorithms sha256crypt and sha512crypt in the pgcrypto extension. These algorithms, implemented in the widely-recognized UNIX crypt(3) password format, provide strong, slow, and tunable hashing with random salts and configurable iteration counts. This makes them much more resistant to brute-force and rainbow table attacks compared to older algorithms like MD5, which are no longer considered secure.

With the new gen_salt() function generating salts that embed the algorithm type and iteration count (defaulting to 5000 rounds but adjustable from 1000 up to nearly a billion), and the crypt() function producing the hashed password, PostgreSQL 18 enables modern and flexible password hashing fully within the database. SHA-2 support may not make headlines, but it’s a practical, modern, and necessary improvement. Whether you’re storing app user credentials, managing internal access controls, or just want to stay aligned with cryptographic best practices, this upgrade is a welcome addition to PostgreSQL’s security toolkit.

Up next in the Security track:
This is just the first of four security-focused highlights from PostgreSQL 18. Stay tuned for:

  • TLS v1.3 cipher suite allowlisting
  • OAuth Authentication and Authorization
  • FIPS mode validation

Each post will include examples, use cases, and commentary on how these features contribute to a more secure PostgreSQL deployment. Stay tuned!

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top