scramp: SCRAM Protocol Implementation

1.4.8 · active · verified Sat Mar 28

scramp is a pure-Python implementation of the SCRAM (Salted Challenge Response Authentication Mechanism) authentication protocol. It supports various SCRAM mechanisms including SCRAM-SHA-1, SCRAM-SHA-256, SCRAM-SHA-512, SCRAM-SHA3-512, and their channel-binding ('-PLUS') variants. The library is currently at version 1.4.8 (as of January 6, 2026) and maintains an active development status with moderate release cadence.

Warnings

Install

Imports

Quickstart

This quickstart demonstrates a basic SCRAM authentication flow between a client and a server. The server initializes a `ScramMechanism` with the user's password to generate and store authentication information. The client then initiates the exchange using `ScramClient`, sending messages back and forth with the server until authentication is complete. The password for the server-side setup is retrieved from an environment variable `SCRAMP_TEST_PASSWORD` for security best practices.

import os
from scramp import ScramClient, ScramMechanism

# --- Server Side Setup ---
username = "user@example.com"
password = os.environ.get('SCRAMP_TEST_PASSWORD', 'test_password') # In a real app, load from secure config

# Server mechanism (stores user's SCRAM data derived from password)
# In a real application, auth_info would be retrieved from a database for the given username.
server_mechanism = ScramMechanism(password=password)
server_auth_info = server_mechanism.make_auth_info(password) # Derived data to store/retrieve for user

print("Server: Initialized SCRAM mechanism and derived auth info.")

# --- Client Side Exchange ---
client = ScramClient(
    mechanisms=['SCRAM-SHA-256'], # Client offers preferred mechanisms
    username=username,
    password=password
)
print(f"Client: Initialized SCRAM client for user '{username}'.")

# 1. Client sends initial message
client_first_message = client.build_client_first_message()
print(f"Client: Sending client-first-message: {client_first_message}")

# 2. Server receives client-first-message and builds server-first-message
# In a real server, 'server_auth_info' would be loaded from a DB based on 'username'
server_first_message = server_mechanism.build_server_first_message(
    client_first_message, server_auth_info
)
print(f"Server: Sending server-first-message: {server_first_message}")

# 3. Client receives server-first-message and builds client-final-message
client_final_message = client.build_client_final_message(server_first_message)
print(f"Client: Sending client-final-message: {client_final_message}")

# 4. Server receives client-final-message and authenticates
server_final_message = server_mechanism.build_server_final_message(
    client_final_message, server_auth_info
)

if server_mechanism.authenticated:
    print("Server: Client authenticated successfully!")
    print(f"Server: Sending server-final-message: {server_final_message}")
else:
    print("Server: Authentication failed.")

# 5. Client receives server-final-message (for verification and channel binding)
try:
    client.verify_server_final_message(server_final_message)
    print("Client: Server final message verified (authentication successful from client perspective).")
except ValueError as e:
    print(f"Client: Server final message verification failed: {e}")

view raw JSON →