Pure Python SRP-6a client implementation with GSA mode support
Project description
srp6
A pure Python implementation of the Secure Remote Password protocol (SRP version 6a) with GSA mode support.
Overview
SRP (Secure Remote Password) is a password-authenticated key exchange protocol that allows secure authentication without transmitting the password over the network. This implementation follows RFC 5054 and includes support for GSA (Grand Slam Authentication) mode.
Features
- Pure Python - No external dependencies, uses only Python standard library
- Multiple Key Sizes - Support for 1024 to 8192-bit primes from RFC 5054
- GSA Mode - Compatible with GSA authentication services
- Hash Cash - Includes proof-of-work implementation for rate limiting
- Type Hints - Full type annotation support
Installation
pip install srp6
Usage
Basic SRP Client
from srp6 import SRPClient, pbkdf2_sha256
# Create client with username
client = SRPClient(b"user@example.com")
# Derive password using PBKDF2 (typically from server's salt)
password = b"secret_password"
salt = b"server_provided_salt"
derived_password = pbkdf2_sha256(password, salt, iterations=10000)
client.password = derived_password
# Get public ephemeral to send to server
A = client.get_public_ephemeral()
# After receiving server's salt and public ephemeral B:
# Generate client proof M1
M1 = client.generate(salt=server_salt, server_public=server_B)
# Get session key for encrypted communication
session_key = client.session_key
Using Different Prime Groups
from srp6 import SRPClient, SRP_1024, SRP_4096
# Use 1024-bit prime (faster, less secure)
client_1024 = SRPClient(b"user", group=1024)
# Use 4096-bit prime (slower, more secure)
client_4096 = SRPClient(b"user", group=4096)
# Or pass the group directly
client = SRPClient(b"user", group=SRP_4096)
Hash Cash (Proof of Work)
from srp6 import generate_hashcash, verify_hashcash
# Generate proof of work
bits = 11 # Difficulty level (number of leading zero bits)
challenge = "server_challenge_string"
hashcash = generate_hashcash(bits, challenge)
# Verify proof of work
is_valid = verify_hashcash(hashcash, bits)
API Reference
SRPClient
class SRPClient:
def __init__(
self,
username: bytes,
a: int | None = None,
group: SRPGroup | int | None = None
):
"""
Initialize SRP client.
Args:
username: The username/identity bytes
a: Optional private ephemeral value (for testing)
group: SRP group - SRPGroup instance, bit size (1024/2048/4096), or None for default (2048)
"""
Properties:
password- Set the derived password (from PBKDF2)session_key- Get the computed session key KM- Get the client proof M1group- Get the SRP group being used
Methods:
get_public_ephemeral()- Get client's public ephemeral Agenerate(salt, server_public)- Generate client proof M1generate_m2()- Generate M2 for verification
Prime Groups
All groups from RFC 5054 (1024 to 8192 bits):
SRP_1024- 1024 bits (128 bytes) - Legacy, not recommendedSRP_1536- 1536 bits (192 bytes) - LegacySRP_2048- 2048 bits (256 bytes) - Standard (default)SRP_3072- 3072 bits (384 bytes) - Enhanced securitySRP_4096- 4096 bits (512 bytes) - High securitySRP_6144- 6144 bits (768 bytes) - Very high securitySRP_8192- 8192 bits (1024 bytes) - Maximum security
Utility Functions
# Hashing
hash_sha256(data: bytes) -> bytes
pbkdf2_sha256(password: bytes, salt: bytes, iterations: int, dklen: int = 32) -> bytes
# Byte conversions
bytes_to_int(b: bytes) -> int
int_to_bytes(n: int, length: int | None = None) -> bytes
to_hex(data: bytes) -> str
from_hex(hex_str: str) -> bytes
GSA Mode
This implementation supports GSA (Grand Slam Authentication) mode, which differs from standard SRP-6a in the following ways:
-
Identity not included in x computation - The password verifier x is computed as
H(salt || H(":" || password))instead ofH(salt || H(I || ":" || password)) -
Generator padding - The generator g is padded to N_BYTES when computing
H(g)for the M1 proof -
No padding for A, B, S - The public ephemerals A and B, and the shared secret S are NOT padded in their respective computations
Protocol Details
Notation
N- Large safe prime (N = 2q+1, where q is prime)g- Generator modulo Nk- Multiplier parameter:k = H(N || pad(g))s- User's saltI- Usernamep- Cleartext passwordH()- One-way hash function (SHA-256)x- Private key derived from password and saltv- Password verifier stored on servera,b- Secret ephemeral valuesA,B- Public ephemeral valuesS- Premaster secretK- Session keyM1,M2- Proofs
Registration (One-Time Setup)
x = H(s || H(I || ":" || p)) # Private key
v = g^x % N # Verifier (stored on server)
The server stores: (I, s, v). The password p is never stored.
Authentication Handshake
Client Server
------ ------
| |
| -------- I, A = g^a % N ------> |
| |
| <------- s, B = kv + g^b % N -- |
| |
| u = H(pad(A) || pad(B)) | u = H(pad(A) || pad(B))
| x = H(s || H(I || ":" || p)) |
| S = (B - kg^x)^(a + ux) % N | S = (Av^u)^b % N
| K = H(S) | K = H(S)
| |
| -------- M1 = H(...) ----------> | (verify M1)
| |
| (verify M2) <------ M2 = H(...) -- |
| |
| [Session key K established] |
Client Calculations
- Generate random
a, computeA = g^a % N - Receive
s,Bfrom server - Compute
u = H(pad(A) || pad(B)) - Compute
k = H(N || pad(g)) - Derive
x = H(s || H(I || ":" || p)) - Compute
S = (B - k * g^x)^(a + u*x) % N - Compute session key
K = H(S) - Compute proof
M1 = H(H(N) XOR H(g) || H(I) || s || A || B || K)
Server Calculations
- Look up
s,vfor userI - Generate random
b, computeB = k*v + g^b % N - Receive
Afrom client - Compute
u = H(pad(A) || pad(B)) - Compute
S = (A * v^u)^b % N - Compute session key
K = H(S) - Verify client proof
M1 - Compute server proof
M2 = H(A || M1 || K)
Security Safeguards
The protocol aborts if any of these conditions occur:
- Client aborts if
B % N == 0(malicious server) - Client aborts if
u == 0(compromised exchange) - Server aborts if
A % N == 0(malicious client) - Server aborts if client proof
M1is invalid
Protocol Flow Diagram
Client Server
------ ------
| |
| -------- username, A --------> |
| |
| <------- salt, B ------------- |
| |
| -------- M1 (proof) ---------> |
| |
| <------- M2 (verification) --- |
| |
| [Session key K established] |
Examples
See the examples directory for complete working examples:
- 01_signup.py - User registration, generating salt and verifier
- 02_authentication.py - Complete authentication handshake
- 03_different_groups.py - Using different prime group sizes
- 04_hashcash.py - Hash cash proof-of-work for rate limiting
Run examples:
python examples/01_signup.py
python examples/02_authentication.py
References
- RFC 2945 - The SRP Authentication and Key Exchange System
- RFC 5054 - Using SRP for TLS Authentication
- Stanford SRP Homepage
License
MIT License - see LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file srp6-0.1.1.tar.gz.
File metadata
- Download URL: srp6-0.1.1.tar.gz
- Upload date:
- Size: 12.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9deca3d8d1592c65a442cc491e0fbf9f75280877cbcca4f74d7ca12129e5241c
|
|
| MD5 |
57c640a6b43ec608ae9bbd359b18a8f0
|
|
| BLAKE2b-256 |
f81bc001742d1bf99834e59e1367a62c4c03139c4291ac751b3632fd166521c6
|
Provenance
The following attestation bundles were made for srp6-0.1.1.tar.gz:
Publisher:
publish.yml on bigbag/srp6
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
srp6-0.1.1.tar.gz -
Subject digest:
9deca3d8d1592c65a442cc491e0fbf9f75280877cbcca4f74d7ca12129e5241c - Sigstore transparency entry: 833697462
- Sigstore integration time:
-
Permalink:
bigbag/srp6@24d5bcaedf3b01df6f2a27c986f208dfa8533295 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/bigbag
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@24d5bcaedf3b01df6f2a27c986f208dfa8533295 -
Trigger Event:
push
-
Statement type:
File details
Details for the file srp6-0.1.1-py3-none-any.whl.
File metadata
- Download URL: srp6-0.1.1-py3-none-any.whl
- Upload date:
- Size: 13.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0acb5a909168c8cf2d572e7786427a292193de392cbe771a3b0cb66d9021bf08
|
|
| MD5 |
074135556b2b38c793fdc8147bea9742
|
|
| BLAKE2b-256 |
519167c0d3b0e4b3e0b5cc196a31f9f0e8c6c3844e855ffe0792866564505db6
|
Provenance
The following attestation bundles were made for srp6-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on bigbag/srp6
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
srp6-0.1.1-py3-none-any.whl -
Subject digest:
0acb5a909168c8cf2d572e7786427a292193de392cbe771a3b0cb66d9021bf08 - Sigstore transparency entry: 833697463
- Sigstore integration time:
-
Permalink:
bigbag/srp6@24d5bcaedf3b01df6f2a27c986f208dfa8533295 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/bigbag
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@24d5bcaedf3b01df6f2a27c986f208dfa8533295 -
Trigger Event:
push
-
Statement type: