Skip to main content

Pure Python SRP-6a client implementation with GSA mode support

Project description

srp6

CI pypi downloads versions license

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 K
  • M - Get the client proof M1
  • group - Get the SRP group being used

Methods:

  • get_public_ephemeral() - Get client's public ephemeral A
  • generate(salt, server_public) - Generate client proof M1
  • generate_m2() - Generate M2 for verification

Prime Groups

All groups from RFC 5054 (1024 to 8192 bits):

  • SRP_1024 - 1024 bits (128 bytes) - Legacy, not recommended
  • SRP_1536 - 1536 bits (192 bytes) - Legacy
  • SRP_2048 - 2048 bits (256 bytes) - Standard (default)
  • SRP_3072 - 3072 bits (384 bytes) - Enhanced security
  • SRP_4096 - 4096 bits (512 bytes) - High security
  • SRP_6144 - 6144 bits (768 bytes) - Very high security
  • SRP_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:

  1. Identity not included in x computation - The password verifier x is computed as H(salt || H(":" || password)) instead of H(salt || H(I || ":" || password))

  2. Generator padding - The generator g is padded to N_BYTES when computing H(g) for the M1 proof

  3. 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 N
  • k - Multiplier parameter: k = H(N || pad(g))
  • s - User's salt
  • I - Username
  • p - Cleartext password
  • H() - One-way hash function (SHA-256)
  • x - Private key derived from password and salt
  • v - Password verifier stored on server
  • a, b - Secret ephemeral values
  • A, B - Public ephemeral values
  • S - Premaster secret
  • K - Session key
  • M1, 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

  1. Generate random a, compute A = g^a % N
  2. Receive s, B from server
  3. Compute u = H(pad(A) || pad(B))
  4. Compute k = H(N || pad(g))
  5. Derive x = H(s || H(I || ":" || p))
  6. Compute S = (B - k * g^x)^(a + u*x) % N
  7. Compute session key K = H(S)
  8. Compute proof M1 = H(H(N) XOR H(g) || H(I) || s || A || B || K)

Server Calculations

  1. Look up s, v for user I
  2. Generate random b, compute B = k*v + g^b % N
  3. Receive A from client
  4. Compute u = H(pad(A) || pad(B))
  5. Compute S = (A * v^u)^b % N
  6. Compute session key K = H(S)
  7. Verify client proof M1
  8. 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 M1 is 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:

Run examples:

python examples/01_signup.py
python examples/02_authentication.py

References

License

MIT License - see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

srp6-0.1.1.tar.gz (12.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

srp6-0.1.1-py3-none-any.whl (13.0 kB view details)

Uploaded Python 3

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

Hashes for srp6-0.1.1.tar.gz
Algorithm Hash digest
SHA256 9deca3d8d1592c65a442cc491e0fbf9f75280877cbcca4f74d7ca12129e5241c
MD5 57c640a6b43ec608ae9bbd359b18a8f0
BLAKE2b-256 f81bc001742d1bf99834e59e1367a62c4c03139c4291ac751b3632fd166521c6

See more details on using hashes here.

Provenance

The following attestation bundles were made for srp6-0.1.1.tar.gz:

Publisher: publish.yml on bigbag/srp6

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for srp6-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 0acb5a909168c8cf2d572e7786427a292193de392cbe771a3b0cb66d9021bf08
MD5 074135556b2b38c793fdc8147bea9742
BLAKE2b-256 519167c0d3b0e4b3e0b5cc196a31f9f0e8c6c3844e855ffe0792866564505db6

See more details on using hashes here.

Provenance

The following attestation bundles were made for srp6-0.1.1-py3-none-any.whl:

Publisher: publish.yml on bigbag/srp6

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page