{"id":703,"library":"scramp","title":"scramp: SCRAM Protocol Implementation","description":"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.","status":"active","version":"1.4.8","language":"python","source_language":"en","source_url":"https://github.com/tlocke/scramp","tags":["authentication","SCRAM","security","protocol","client","server"],"install":[{"cmd":"pip install scramp","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Often used for flexible server-side password hashing (e.g., PBKDF2). Not a strict runtime dependency for basic operation, but enables advanced server-side customization.","package":"passlib","optional":true}],"imports":[{"symbol":"ScramClient","correct":"from scramp import ScramClient"},{"symbol":"ScramMechanism","correct":"from scramp import ScramMechanism"}],"quickstart":{"code":"import os\nfrom scramp import ScramClient, ScramMechanism\n\n# --- Server Side Setup ---\nusername = \"user@example.com\"\npassword = os.environ.get('SCRAMP_TEST_PASSWORD', 'test_password') # In a real app, load from secure config\n\n# Server mechanism (stores user's SCRAM data derived from password)\n# In a real application, auth_info would be retrieved from a database for the given username.\nserver_mechanism = ScramMechanism(password=password)\nserver_auth_info = server_mechanism.make_auth_info(password) # Derived data to store/retrieve for user\n\nprint(\"Server: Initialized SCRAM mechanism and derived auth info.\")\n\n# --- Client Side Exchange ---\nclient = ScramClient(\n    mechanisms=['SCRAM-SHA-256'], # Client offers preferred mechanisms\n    username=username,\n    password=password\n)\nprint(f\"Client: Initialized SCRAM client for user '{username}'.\")\n\n# 1. Client sends initial message\nclient_first_message = client.build_client_first_message()\nprint(f\"Client: Sending client-first-message: {client_first_message}\")\n\n# 2. Server receives client-first-message and builds server-first-message\n# In a real server, 'server_auth_info' would be loaded from a DB based on 'username'\nserver_first_message = server_mechanism.build_server_first_message(\n    client_first_message, server_auth_info\n)\nprint(f\"Server: Sending server-first-message: {server_first_message}\")\n\n# 3. Client receives server-first-message and builds client-final-message\nclient_final_message = client.build_client_final_message(server_first_message)\nprint(f\"Client: Sending client-final-message: {client_final_message}\")\n\n# 4. Server receives client-final-message and authenticates\nserver_final_message = server_mechanism.build_server_final_message(\n    client_final_message, server_auth_info\n)\n\nif server_mechanism.authenticated:\n    print(\"Server: Client authenticated successfully!\")\n    print(f\"Server: Sending server-final-message: {server_final_message}\")\nelse:\n    print(\"Server: Authentication failed.\")\n\n# 5. Client receives server-final-message (for verification and channel binding)\ntry:\n    client.verify_server_final_message(server_final_message)\n    print(\"Client: Server final message verified (authentication successful from client perspective).\")\nexcept ValueError as e:\n    print(f\"Client: Server final message verification failed: {e}\")","lang":"python","description":"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."},"warnings":[{"fix":"Review server-side implementations (e.g., `make_auth_info`, `build_server_first_message`) and adapt to the updated API, especially if custom authentication databases or hashing functions are used.","message":"Version 1.2.0 introduced backward-incompatible changes to the server-side API. This update modified how authentication information is handled to enable storing derived user data (e.g., in a database) and integrate with third-party hashing libraries like `passlib`.","severity":"breaking","affected_versions":">=1.2.0"},{"fix":"When initializing `ScramClient`, pass `channel_binding=('tls-server-end-point', your_tls_data)` or similar if channel binding is desired for stronger security.","message":"`ScramClient` selects the most secure mechanism from a provided list. To use channel-binding (`-PLUS`) variants, the `channel_binding` parameter (a tuple of name and data) must be explicitly provided during `ScramClient` initialization. If `channel_binding` is `None`, `-PLUS` mechanisms will be filtered out.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always verify the PyPI project description and source URL to confirm you are using `scramp` for SCRAM authentication, not a similarly named library with different functionality.","message":"The package name `scramp` is easily confused with other Python libraries or projects (e.g., `scamp` for music, `SCAMP`/`pyscamp` for matrix profiles, `SCaMP` for metagenomics, `SCRAP` for RNA-seq, Scamp5d vision system). Ensure you are installing and importing `scramp` specifically for SCRAM protocol implementation.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-05-12T17:58:19.298Z","next_check":"2026-06-26T00:00:00.000Z","problems":[{"fix":"pip install scramp","cause":"The 'scramp' library is not installed in the current Python environment.","error":"ModuleNotFoundError: No module named 'scramp'"},{"fix":"Encode the string to bytes, typically using `.encode('utf-8')`. Example: `client.set_password('mysecret'.encode('utf-8'))`","cause":"A Python string (`str`) was provided to a 'scramp' function or method that expects a byte string (`bytes`), often for sensitive data like passwords or salts.","error":"TypeError: a bytes-like object is required, not 'str'"},{"fix":"Verify the provided username, password, salt, and iteration count (N). Ensure both client and server are correctly following the SCRAM message exchange sequence and data integrity.","cause":"The SCRAM authentication exchange failed due to incorrect credentials (username, password), invalid proofs, or a violation of the authentication protocol steps.","error":"scramp.exceptions.ScrampError: Authentication failed"},{"fix":"Ensure that the client requests a mechanism that is present in the server's list of supported mechanisms, or configure the server to include the desired mechanism in its `mechanisms` parameter during instantiation.","cause":"The client attempted to negotiate an authentication mechanism (e.g., 'SCRAM-SHA-128') that the 'scramp' server instance was not configured to support or did not advertise as available.","error":"ValueError: Auth mechanism 'SCRAM-SHA-128' not supported by server"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":0,"quickstart_tag":"stale","pypi_latest":"1.4.8","install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.14,"mem_mb":6.1,"disk_size":"18.8M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.16,"mem_mb":6.1,"disk_size":"18.8M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.7,"import_time_s":0.11,"mem_mb":6.1,"disk_size":"19M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.11,"mem_mb":6.1,"disk_size":"19M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.22,"mem_mb":7,"disk_size":"20.9M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.26,"mem_mb":7,"disk_size":"20.9M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.7,"import_time_s":0.19,"mem_mb":7,"disk_size":"21M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.19,"mem_mb":7,"disk_size":"21M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.19,"mem_mb":6.7,"disk_size":"12.7M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.19,"mem_mb":6.7,"disk_size":"12.7M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.8,"import_time_s":0.19,"mem_mb":6.7,"disk_size":"13M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.19,"mem_mb":6.7,"disk_size":"13M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.18,"mem_mb":7,"disk_size":"12.4M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.19,"mem_mb":7,"disk_size":"12.3M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.6,"import_time_s":0.18,"mem_mb":7,"disk_size":"13M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.19,"mem_mb":7,"disk_size":"13M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.14,"mem_mb":6.3,"disk_size":"18.3M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.15,"mem_mb":6.3,"disk_size":"18.3M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.8,"import_time_s":0.12,"mem_mb":6.3,"disk_size":"19M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.12,"mem_mb":6.3,"disk_size":"19M"}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":"stale","tag_description":"widespread failures or data too old to trust","results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}