summaryrefslogtreecommitdiff
path: root/doc/srp.rst
blob: ef55addbdb66015a7272f528ee27f678ad3887f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
:mod:`srp` --- Secure Remote Password
=====================================

.. module:: srp
    :synopsis: Secure Remote Password
    
.. moduleauthor:: Tom Cocagne <tom.cocagne@gmail.com>

.. sectionauthor:: Tom Cocagne <tom.cocagne@gmail.com>


This module provides an implementation of the Secure Remote Password
Protocol. It is 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 subsequent
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.

The User & Verifier construtors, as well as the gen_sv() function,
take optional hashing algorithm and prime number arguments. Generally
speaking, more bits means more computation time and more security. The
hashing and prime number parameters passed to the User and Verifier
constructors must match those used to create the verification key.

See http://srp.stanford.edu/ for a full description of the SRP protocol.

Constants
---------
==============  ==============
Hash Algorithm  Number of Bits
==============  ==============
SHA1            160
SHA224          224
SHA256          256
SHA384          384
SHA512          512
==============  ==============

=================
Prime Number Size
=================
NG_1024  
NG_2048   
NG_4096   
NG_CUSTOM 
=================

If NG_CUSTOM is used, the 'n_hex' and 'g_hex' parameters are required.
These parameters must be ASCII text containing hexidecimal notation of the
prime number 'n_hex' and the corresponding generator number 'g_hex'. Appendix
A of RFC 5054 contains several large prime number, generator pairs that may
be used with NG_CUSTOM.

Functions
---------

.. function:: gen_sv ( username, password[, hash_alg=SHA1, ng_type=NG_1024, n_hex=None, g_hex=None] )

    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[, hash_alg=SHA1, ng_type=NG_1024, n_hex=None, g_hex=None] )

  *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[, hash_alg=SHA1, ng_type=NG_1024, n_hex=None, g_hex=None] )

  *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()