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
sha256cryptandsha512cryptuse 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.
| Algorithm | Max Password Length | Adaptive? | Salt Bits | Output Length | Description |
| sha256crypt | unlimited | yes | up to 32 | 80 | Adapted from publicly available reference implementation SHA-crypt.txt |
| sha512crypt | unlimited | yes | up to 32 | 123 | Adapted 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 round | 1000(Min) | 5000(Default) | 10000 | 50000 | 100000 |
| sha256crypt | 0.653 ms | 3.492 ms | 6.698 ms | 37.918 ms | 82.520 ms |
| sha512crypt | 0.570 ms | 2.520 ms | 6.362 ms | 32.116 ms | 64.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!
