Skip to content

SCRAM-SHA-256 Quick Reference

SCRAM-SHA-256 Quick Reference

Fast reference for SCRAM-SHA-256 authentication in HeliosDB Nano.

Quick Setup

use heliosdb_nano::protocol::postgres::{
PgServerBuilder, AuthMethod, AuthManager,
InMemoryPasswordStore, SharedPasswordStore
};
use std::sync::Arc;
// 1. Create password store and add users
let mut store = InMemoryPasswordStore::new();
store.add_user("postgres", "password")?;
// 2. Wrap in shared store
let shared = SharedPasswordStore::new(store);
// 3. Create auth manager
let auth = Arc::new(
AuthManager::with_password_store(AuthMethod::ScramSha256, shared)
);
// 4. Build server
let server = PgServerBuilder::new()
.address("127.0.0.1:5432".parse()?)
.auth_manager(auth)
.build(db)?;

Connect with psql

Terminal window
# Direct password
psql "host=127.0.0.1 port=5432 user=postgres password=password"
# Interactive prompt
psql "host=127.0.0.1 port=5432 user=postgres"
# With SSL
psql "sslmode=require host=127.0.0.1 port=5432 user=postgres password=password"

User Management

let mut store = InMemoryPasswordStore::new();
// Add user
store.add_user("alice", "secret")?;
// Update password
store.update_password("alice", "new_secret")?;
// Remove user
store.remove_user("alice")?;
// Check existence
if store.user_exists("alice") { ... }
// List users
let users = store.list_users();

Custom Iterations

// Higher security (slower)
let store = InMemoryPasswordStore::with_iterations(8192);
// Development (faster)
let store = InMemoryPasswordStore::with_iterations(4096);

Authentication Methods

// SCRAM-SHA-256 (recommended)
AuthMethod::ScramSha256
// Trust (development only)
AuthMethod::Trust
// Cleartext (not recommended)
AuthMethod::CleartextPassword
// MD5 (legacy)
AuthMethod::Md5

File Locations

ComponentFile Path
Core Implementationsrc/protocol/postgres/auth.rs
Password Storesrc/protocol/postgres/password_store.rs
Protocol Handlersrc/protocol/postgres/handler.rs
Teststests/postgres_scram_auth_tests.rs
Exampleexamples/postgres_server_ssl.rs
Documentationdocs/SCRAM_SHA256_AUTHENTICATION.md

Key Functions

// Credential preparation
let (stored_key, server_key) = prepare_scram_credentials(password, salt, iterations);
// Password verification
let creds = ScramCredentials::from_password("user".to_string(), "password", 4096);
assert!(creds.verify_password("password"));
// SCRAM auth state
let mut state = ScramAuthState::new("username".to_string());
state.set_client_nonce(nonce);
let server_first = state.build_server_first_message()?;

Testing

Terminal window
# Run SCRAM tests
cargo test postgres_scram_auth_tests
# Run all protocol tests
cargo test --test '*protocol*'
# Run example
cargo run --example postgres_server_ssl

Troubleshooting

IssueSolution
”User not found”Add user with store.add_user(username, password)
”Invalid password”Update with store.update_password(username, new_password)
Slow authReduce iterations (4096 is good for development)
Client errorsEnsure client supports SCRAM-SHA-256 (psql 10+)

Security Checklist

  • ✅ Use SCRAM-SHA-256 in production
  • ✅ Combine with SSL/TLS
  • ✅ Use strong passwords (12+ chars)
  • ✅ High iterations (8192+) for production
  • ✅ Implement password rotation
  • ✅ Log authentication events
  • ✅ Use persistent password store

Performance

ConfigurationAuth TimeRecommended For
4096 iterations~10msDevelopment
8192 iterations~20msProduction
16384 iterations~40msHigh Security

Common Patterns

Development Setup

let auth = AuthManager::with_scram_store(AuthMethod::ScramSha256)
.with_default_users();

Production Setup with SSL

let server = PgServerBuilder::new()
.address("0.0.0.0:5432".parse()?)
.auth_manager(scram_auth_manager)
.ssl_config(ssl_config)
.build(db)?;

Custom Password Store

struct MyPasswordStore { /* ... */ }
impl PasswordStore for MyPasswordStore {
fn get_credentials(&self, username: &str) -> Option<ScramCredentials> { ... }
fn add_user(&mut self, username: &str, password: &str) -> Result<()> { ... }
fn remove_user(&mut self, username: &str) -> Result<bool> { ... }
fn update_password(&mut self, username: &str, new_password: &str) -> Result<()> { ... }
fn user_exists(&self, username: &str) -> bool { ... }
fn list_users(&self) -> Vec<String> { ... }
}

RFC References

See Also