srptools
========
https://github.com/idlesign/srptools

.. image:: https://idlesign.github.io/lbc/py2-lbc.svg
   :target: https://idlesign.github.io/lbc/
   :alt: LBC Python 2

----

|release| |stats|  |lic| |ci| |coverage| |health|

.. |release| image:: https://img.shields.io/pypi/v/srptools.svg
    :target: https://pypi.python.org/pypi/srptools

.. |stats| image:: https://img.shields.io/pypi/dm/srptools.svg
    :target: https://pypi.python.org/pypi/srptools

.. |lic| image:: https://img.shields.io/pypi/l/srptools.svg
    :target: https://pypi.python.org/pypi/srptools

.. |ci| image:: https://img.shields.io/travis/idlesign/srptools/master.svg
    :target: https://travis-ci.org/idlesign/srptools

.. |coverage| image:: https://img.shields.io/coveralls/idlesign/srptools/master.svg
    :target: https://coveralls.io/r/idlesign/srptools

.. |health| image:: https://landscape.io/github/idlesign/srptools/master/landscape.svg?style=flat
    :target: https://landscape.io/github/idlesign/srptools/master


Description
-----------

*Tools to implement Secure Remote Password (SRP) authentication*

SRP is a secure password-based authentication and key-exchange protocol -
a password-authenticated key agreement protocol (PAKE).

This package contains protocol implementation for Python 2 and 3.

You may import it into you applications and use its API or you may use
``srptools`` command-line utility (CLI):


CLI usage
---------

Command-line utility requires ``click`` package to be installed.

Basic scenario:

.. code-block::

    > srptools get_user_data_triplet
    > srptools server get_private_and_public
    > srptools client get_private_and_public
    > srptools client get_session_data
    > srptools server get_session_data

Help is available:

.. code-block::

    > srptools --help



API usage
---------

Preliminary step. Agree on communication details:

.. code-block:: python

    from srptools import SRPContext

    context = SRPContext('alice', 'password123')
    username, password_verifier, salt = context.get_user_data_triplet()
    prime = context.prime
    gen = context.generator


Simplified workflow:

.. code-block:: python

    from srptools import SRPContext, SRPServerSession, SRPClientSession

    # Receive username from client and generate server public.
    server_session = SRPServerSession(SRPContext(username, prime=prime, generator=gen), password_verifier)
    server_public = server_session.public

    # Receive server public and salt and process them.
    client_session = SRPClientSession(SRPContext('alice', 'password123', prime=prime, generator=gen))
    client_session.process(server_public, salt)
    # Generate client public and session key.
    client_public = client_session.public

    # Process client public and compare session keys.
    server_session.process(client_public, salt)

    assert server_session.key == client_session.key


Extended workflow

.. code-block:: python

    from srptools import SRPContext, SRPServerSession, SRPClientSession

    # Receive username from client and generate server public.
    server_session = SRPServerSession(SRPContext(username, prime=prime, generator=gen), password_verifier)
    server_public = server_session.public

    # Receive server public and salt and process them.
    client_session = SRPClientSession(SRPContext('alice', 'password123', prime=prime, generator=gen))
    client_session.process(server_public, salt)
    # Generate client public and session key proof.
    client_public = client_session.public
    client_session_key_proof = client_session.key_proof

    # Process client public and verify session key proof.
    server_session.process(client_public, salt)
    assert server_session.verify_proof(client_session_key_proof)
    # Generate session key proof hash.
    server_session_key_proof_hash = client_session.key_proof_hash

    # Verify session key proof hash received from server.
    assert client_session.verify_proof(server_session_key_proof_hash)



Usage hints
-----------

* ``srptools.constants`` contains basic constants which can be used with ``SRPContext`` for server and client to agree
  upon communication details.
* ``.process()`` methods of session classes may raise ``SRPException`` in certain circumstances. Auth process on
  such occasions must be stopped.
* ``.private`` attribute of session classes may be used to restore sessions:
    .. code-block:: python

        server_private = server_session.private

        # Restore session on new request.
        server_session = SRPServerSession(context, password_verifier, private=server_private)

* ``SRPContext`` is rather flexible, so you can implement some custom server/client session logic with its help.
* Basic values are represented as hex strings but base64 encoded values are also supported:

    .. code-block:: python

        server_public = server_session.public_b64

        # Receive server public and salt and process them.
        client_session = SRPClientSession(SRPContext('alice', 'password123', prime=prime, generator=gen))
        client_session.process(server_public, salt, base64=True)

        # Use srptools.hex_from_b64() to represent base64 value as hex.
        server_public_hex = hex_from_b64(server_public)


Links
-----
* RFC 2945 - The SRP Authentication and Key Exchange System
    https://tools.ietf.org/html/rfc2945

* RFC 5054 - Using the Secure Remote Password (SRP) Protocol for TLS Authentication
    https://tools.ietf.org/html/rfc5054
