SPAKE2 Password-Authenticated Key Exchange

0.9 · active · verified Thu Apr 16

The `spake2` library is a pure-Python implementation of the SPAKE2 password-authenticated key exchange (PAKE) algorithm. It enables two parties sharing a weak password to securely derive a strong shared secret over an insecure channel, preventing passive eavesdropping and limiting active attackers to a single password guess per protocol execution. The current stable version is 0.9, released in September 2024, with an infrequent release cadence.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates a basic SPAKE2 key exchange between two parties, Alice (role A) and Bob (role B), who share a weak password. Both parties initialize their respective SPAKE2 instances with the shared password and unique identity strings. They then exchange initial messages, process the received message, and derive a strong, shared secret key. The `idA` and `idB` strings are crucial for binding the key to specific parties and preventing replay/substitution attacks. The example uses `ParamsEd25519` for elliptic curve security.

import os
from spake2 import SPAKE2_A, SPAKE2_B
from spake2.parameters.all import ParamsEd25519 # Or other parameter sets like Params3072

def run_spake2_exchange(password: bytes, idA: bytes, idB: bytes):
    # Alice (Side A)
    alice = SPAKE2_A(password, idA=idA, idB=idB, params=ParamsEd25519)
    alice_msg = alice.start()

    # Bob (Side B)
    bob = SPAKE2_B(password, idA=idA, idB=idB, params=ParamsEd25519)
    bob_msg = bob.start()

    # Exchange messages
    # In a real application, alice_msg would be sent to Bob, and bob_msg to Alice.
    # For this example, we directly pass them.

    # Alice processes Bob's message
    alice_key = alice.finish(bob_msg)

    # Bob processes Alice's message
    bob_key = bob.finish(alice_msg)

    print(f"Alice's derived key: {alice_key.hex()}")
    print(f"Bob's derived key:   {bob_key.hex()}")

    if alice_key == bob_key:
        print("\nShared secret derived successfully!")
        return alice_key
    else:
        print("\nFailed to derive shared secret. Keys do not match.")
        return None

if __name__ == "__main__":
    # Example usage
    shared_password = os.environ.get('SPAKE2_PASSWORD', 'test-password').encode('utf-8')
    alice_id = b"Alice"
    bob_id = b"BobServer"

    print(f"Using password: {shared_password.decode('utf-8')}")
    print(f"Alice ID: {alice_id.decode('utf-8')}, Bob ID: {bob_id.decode('utf-8')}")

    derived_key = run_spake2_exchange(shared_password, alice_id, bob_id)
    if derived_key:
        # The derived key can then be used for symmetric encryption, HMAC, or fed into HKDF.
        print(f"Using derived key for subsequent secure communication.")

view raw JSON →