:mod:`srp` --- Secure Remote Password ===================================== .. module:: srp :synopsis: Secure Remote Password .. moduleauthor:: Tom Cocagne .. sectionauthor:: Tom Cocagne This module provides an implementation of the Secure Remote Password Protocol. It may be used for secure authentication across an unsecured network connection and verifies that both sides, the user and server, have knowledge of the user's password. Unlike other commonly used authentication protocols such as Kerberos and certificate-based SSL, SRP does not require a trusted third party. With SRP, the user's password is never sent over the network and a successful authentication results in a cryptographically secure shared key that may be used for symmetric key encryption. SRP authentication requires the server to store a salted verification key that is computed from user's password. While care should be taken to protect the verification key from disclosure, the protocol remains reasonably secure even in the event that an attacker obtains it. The verification key cannot be used to directly impersonate the user and it would require a computationally infeasible brute-force dictionary attack to derive the users password from the verification key. This implementation of SRP consists of both a pure-python module and a C-based implementation that is approximately 10x faster. By default, the C-implementation will be used if it is available. An additional benefit of the C implementation is that it can take advantage of of multiple CPUs. For cases in which the number of connections per second is an issue, using a small pool of threads to perform the authentication steps on multi-core systems will yield a substantial performance increase. See http://srp.stanford.edu/ for a full description of the SRP protocol. Functions --------- .. function:: gen_sv ( username, password ) Generates a salt and verifier for the given username and password. Returns (salt_bytes, verifier_bytes) :class:`Verifier` Objects ------------------------- A :class:`Verifier` object is used to verify the identity of a remote user. .. note:: The standard SRP 6 protocol allows only one password attempt per connection. .. class:: Verifier( username, bytes_s, bytes_v, bytes_A ) *username* Name of the remote user being authenticated. *bytes_s* Salt generated by :func:`gen_sv`. *bytes_v* Verifier generated by :func:`gen_sv`. *bytes_A* Challenge from the remote user. Generated by :meth:`User.start_authentication` .. method:: Verifier.authenticated() Returns True if the authentication succeeded. False otherwise. .. method:: Verifier.get_username() Returns the name of the user this :class:`Verifier` object is for. .. method:: Verifier.get_session_key() Returns the session key for an authenticated user or None if the authentication failed or has not yet completed. .. method:: Verifier.get_challenge() Returns (bytes_s, bytes_B) on success or (None, None) if authentication has failed. .. method:: Verifier.verify_session( user_M ) Completes the :class:`Verifier` side of the authentication process. If the authentication succeded the return result, bytes_H_AMK should be returned to the remote user. On failure, this method returns None. :class:`User` Objects ------------------------- A :class:`User` object is used to perform mutual authentication with a remote :class:`Verifier`. Successful authentication requires not only that the :class:`User` be provided with a valid username/password but also that the remote :class:`Verifier` have a salt & verifier for that username/password pair. .. class:: User( username, password ) *username* Name of the user being authenticated. *password* Password for the user. .. method:: User.authenticated() Returns True if authentication succeeded. False otherwise. .. method:: User.get_username() Returns the username passed to the constructor. .. method:: User.get_session_key() Returns the session key if authentication succeeded or None if the authentication failed or has not yet completed. .. method:: User.start_authentication() Returns (username, bytes_A). These should be passed to the constructor of the remote :class:`Verifer` .. method:: User.process_challenge( bytes_s, bytes_B ) Processes the challenge returned by :meth:`Verifier.get_challenge` on success this method returns bytes_M that should be sent to :meth:`Verifier.verify_session` if authentication failed, it returns None. .. method:: User.verify_session( bytes_H_AMK ) Completes the :class:`User` side of the authentication process. If the authentication succeded :meth:`authenticated` will return True Examples -------- Simple Usage Example:: import srp # The salt and verifier returned from srp.gen_sv() should be # stored on the server. salt, verifier = srp.gen_sv( 'testuser', 'testpassword' ) # ~~~ Begin Authentication ~~~ usr = srp.User( 'testuser', 'testpassword' ) uname, A = usr.start_authentication() # The authentication process can fail at each step from this # point on. To comply with the SRP protocol, the authentication # process should be aborted on the first failure. # Client => Server: username, A svr = srp.Verifier( uname, salt, verifier, A ) s,B = svr.get_challenge() # Server => Client: s, B M = usr.process_challenge( s, B ) # Client => Server: M HAMK = svr.verify_session( M ) # Server => Client: HAMK usr.verify_session( HAMK ) # At this point the authentication process is complete. assert usr.authenticated() assert svr.authenticated()