---
title: "SCRAM-SHA-256 Authentication Guide"
---

# 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

```bash
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

```bash
# 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:

```sql
-- 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

```bash
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

```bash
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

- [RFC 5802 - SCRAM SASL Mechanism](https://tools.ietf.org/html/rfc5802)
- [RFC 7677 - SCRAM-SHA-256](https://tools.ietf.org/html/rfc7677)
- [PostgreSQL SCRAM Documentation](https://www.postgresql.org/docs/current/sasl-authentication.html)
- [PBKDF2 Specification](https://tools.ietf.org/html/rfc2898)

## Support

For issues or questions: [support@heliosdb.com](mailto:support@heliosdb.com)
