Skip to content

SCRAM-SHA-256 Authentication Guide

Complete guide to SCRAM-SHA-256 authentication on the HeliosDB-Lite PostgreSQL port.

Overview

SCRAM-SHA-256 (Salted Challenge Response Authentication Mechanism) is a modern, secure authentication protocol that provides:

  • No plaintext passwords: Passwords are never transmitted or stored in plaintext
  • Mutual authentication: Both client and server prove knowledge of the password
  • Replay attack protection: Each authentication uses unique nonces
  • Timing attack resistance: Constant-time comparison prevents timing-based attacks
  • RFC compliance: Compliant with RFC 5802 (SCRAM) and RFC 7677 (SCRAM-SHA-256)

Quick Start

Basic Setup

Terminal window
export HELIOSDB_JWT_SECRET="$(openssl rand -hex 32)"
export HELIOSDB_ADMIN_PASSWORD='secure_password'
heliosdb-lite start --data-dir ./mydb \
--auth scram-sha-256 --password "$HELIOSDB_ADMIN_PASSWORD"

--password becomes the password of the built-in administrator accounts postgres and helios. Every --auth method except trust requires it.

Connecting with psql

Terminal window
# Interactive password prompt
psql "host=127.0.0.1 port=5432 user=postgres dbname=heliosdb"
# Password from the environment
PGPASSWORD="$HELIOSDB_ADMIN_PASSWORD" psql "host=127.0.0.1 port=5432 user=postgres dbname=heliosdb"
# With SSL/TLS (server started with --tls-cert and --tls-key)
psql "sslmode=require host=127.0.0.1 port=5432 user=postgres"

User Management

Create login roles with SQL; their passwords are stored as SCRAM verifiers:

-- Add a user
CREATE ROLE alice LOGIN PASSWORD 'a-long-random-password';
-- Update a password
ALTER ROLE alice PASSWORD 'another-long-password';
-- Disable password login
ALTER ROLE alice PASSWORD NULL;
-- Remove a user
DROP ROLE alice;

The built-in postgres and helios accounts are resolved first, so a SQL role can never shadow them. A role without LOGIN, or without a password, cannot authenticate.

Authentication Flow

Client Server
| |
|--- Startup (user=alice) --------------->|
| |
|<-- AuthenticationSASL (SCRAM-SHA-256)---|
| |
|--- client-first-message ---------------->|
| (n=alice,r=client_nonce) |
| |
|<-- server-first-message -----------------|
| (r=client_nonce+server_nonce, |
| s=salt_b64,i=iterations) |
| |
|--- client-final-message ---------------->|
| (c=channel_binding, |
| r=combined_nonce, |
| p=client_proof) |
| | [Verify proof]
| |
|<-- server-final-message -----------------|
| (v=server_signature) |
| |
|<-- AuthenticationOk --------------------|
| |
|<-- ReadyForQuery -----------------------|

Security Features

Password Derivation

SCRAM-SHA-256 uses PBKDF2-HMAC-SHA-256 for key derivation:

SaltedPassword = Hi(password, salt, iterations)
ClientKey = HMAC(SaltedPassword, "Client Key")
StoredKey = H(ClientKey)
ServerKey = HMAC(SaltedPassword, "Server Key")

HeliosDB-Lite uses 100,000 PBKDF2 iterations (the NIST SP 800-132 recommendation) and a random salt per user.

Stored Credentials

Only the salt, the iteration count, StoredKey and ServerKey are stored; the plaintext password is never kept.

Timing Attack Resistance

All secret comparisons use constant-time algorithms.

Best Practices

Production Deployment

  1. Use strong passwords: Minimum 12 characters, mixed case, numbers, symbols
  2. Combine with SSL/TLS: Start with --tls-cert / --tls-key and use sslmode=require
  3. Rotate passwords: ALTER ROLE ... PASSWORD on a schedule
  4. Monitor failed attempts: Alert on repeated authentication failures in the server log
  5. Least privilege: Connect applications as non-superuser roles

Troubleshooting

Common Issues

Authentication fails with “User not found”

  • Cause: The role does not exist, has no LOGIN, or has no password
  • Solution: CREATE ROLE ... LOGIN PASSWORD ..., or connect as postgres

Authentication fails with “Invalid password”

  • Cause: Incorrect password
  • Solution: Reset it with ALTER ROLE ... PASSWORD ...

Client shows “SCRAM not supported”

  • Cause: Client doesn’t support SCRAM-SHA-256
  • Solution: Use a modern PostgreSQL client (psql 10+, libpq 10+)

Debug Logging

Terminal window
export HELIOSDB_JWT_SECRET="$(openssl rand -hex 32)"
RUST_LOG=debug heliosdb-lite start --data-dir ./mydb \
--auth scram-sha-256 --password "$HELIOSDB_ADMIN_PASSWORD"

Performance Considerations

Benchmarks

The server uses 100,000 iterations and has no setting to change it; these timings were measured at the lower iteration counts shown and understate the default cost proportionally.

Figures from internal tests (HeliosDB Lite SCRAM path, representative fixtures); reproduce on your own hardware.

At 4,096 iterations:

  • Credential creation: ~5ms
  • Password verification: ~5ms
  • Full authentication: ~10-15ms

At 16,384 iterations:

  • Credential creation: ~20ms
  • Password verification: ~20ms
  • Full authentication: ~40-50ms

Optimization Tips

  1. Connection pooling: Authenticate once, reuse connections (client-side pools or HeliosProxy)
  2. Async operations: Authentication is fully async and does not block other sessions

RFC Compliance

HeliosDB-Lite SCRAM implementation is compliant with:

  • RFC 5802: Salted Challenge Response Authentication Mechanism (SCRAM)
  • RFC 7677: SCRAM-SHA-256
  • PostgreSQL Protocol: SASL authentication messages

Supported Features

  • SCRAM-SHA-256
  • PBKDF2-HMAC-SHA-256 key derivation
  • Salted password hashing
  • Client and server nonce
  • Channel binding placeholder (n,,)
  • Server signature verification
  • Constant-time comparisons

Migration Guide

From Trust to SCRAM

Terminal window
export HELIOSDB_JWT_SECRET="$(openssl rand -hex 32)"
# Before (trust: no passwords)
heliosdb-lite start --data-dir ./mydb
# After (SCRAM)
heliosdb-lite start --data-dir ./mydb --auth scram-sha-256 --password "$HELIOSDB_ADMIN_PASSWORD"

Then create one login role per application with CREATE ROLE ... LOGIN PASSWORD ....

From Cleartext or MD5 to SCRAM

Restart the server with --auth scram-sha-256. Passwords set with CREATE ROLE or ALTER ROLE are already stored as SCRAM verifiers, so no password reset is needed.

References

Support

For issues or questions: support@heliosdb.com