diff options
| author | Ben Carrillo <ben@futeisha.org> | 2013-01-28 09:09:07 +0900 | 
|---|---|---|
| committer | Ben Carrillo <ben@futeisha.org> | 2013-01-28 09:09:07 +0900 | 
| commit | 7761b24a526987fad55af130e20417503d2cea51 (patch) | |
| tree | abdb5628bb63b3937f4242b7f4a01487d321e33a /srp/doc | |
initial packaging attempt
Diffstat (limited to 'srp/doc')
| -rw-r--r-- | srp/doc/conf.py | 216 | ||||
| -rw-r--r-- | srp/doc/index.rst | 22 | ||||
| -rw-r--r-- | srp/doc/srp.rst | 377 | 
3 files changed, 615 insertions, 0 deletions
| diff --git a/srp/doc/conf.py b/srp/doc/conf.py new file mode 100644 index 0000000..ba75a8c --- /dev/null +++ b/srp/doc/conf.py @@ -0,0 +1,216 @@ +# -*- coding: utf-8 -*- +# +# Secure Remote Password documentation build configuration file, created by +# sphinx-quickstart on Fri Mar 25 10:20:52 2011. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = [] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Secure Remote Password' +copyright = u'2011, Tom Cocagne' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '1.0' +# The full version, including alpha/beta/rc tags. +release = '1.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages.  See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further.  For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents.  If None, it defaults to +# "<project> v<release> documentation". +#html_title = None + +# A shorter title for the navigation bar.  Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a <link> tag referring to it.  The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'SecureRemotePassworddoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ +  ('index', 'SecureRemotePassword.tex', u'Secure Remote Password Documentation', +   u'Tom Cocagne', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ +    ('index', 'secureremotepassword', u'Secure Remote Password Documentation', +     [u'Tom Cocagne'], 1) +] diff --git a/srp/doc/index.rst b/srp/doc/index.rst new file mode 100644 index 0000000..0c13606 --- /dev/null +++ b/srp/doc/index.rst @@ -0,0 +1,22 @@ +.. Secure Remote Password documentation master file, created by +   sphinx-quickstart on Fri Mar 25 10:20:52 2011. +   You can adapt this file completely to your liking, but it should at least +   contain the root `toctree` directive. + +Welcome to Secure Remote Password's documentation! +================================================== + +Contents: + +.. toctree:: +   :maxdepth: 2 + +   srp.rst + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/srp/doc/srp.rst b/srp/doc/srp.rst new file mode 100644 index 0000000..9cdd967 --- /dev/null +++ b/srp/doc/srp.rst @@ -0,0 +1,377 @@ +: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> + + +The Secure Remote Password protocol (SRP) is a cryptographically +strong authentication protocol for password-based, mutual +authentication over an insecure network connection. Successful SRP +authentication requires both sides of the connection to have knowledge +of the user's password. In addition to password verification, the SRP +protocol also performs a secure key exchange during the authentication +process. This key may be used to protect network traffic via symmetric +key encryption. + +SRP offers security and deployment advantages over other +challenge-response protocols, such as Kerberos and SSL, in that it +does not require trusted key servers or certificate infrastructures. +Instead, small verification keys derived from each user's password are +stored and used by each SRP server application. SRP provides a +near-ideal solution for many applications requiring simple and secure +password authentication that does not rely on an external +infrastructure. + +Another favorable aspect of the SRP protocol is that compromized +verification keys are of little value to an attacker. Possesion of a +verification key does not allow a user to be impersonated +and it cannot be used to obtain the users password except by way of a +computationally infeasible dictionary attack. A compromized key would, +however, allow an attacker to impersonate the server side of an SRP +authenticated connection. Consequently, care should be taken to +prevent unauthorized access to verification keys for applications in +which the client side relies on the server being genuine. + + + +Usage +----- + +SRP usage begins with *create_salted_verification_key()*. This function +creates a salted verification key from the user's password. The resulting salt +and key are stored by the server application and will be used during the +authentication process. + +The authentication process occurs as an exchange of messages between the clent +and the server. The :ref:`example` below provides a simple demonstration of the +protocol. A comprehensive description of the SRP protocol is contained in the +:ref:`protocol-description` section. + +The *User* & *Verifier* constructors, as well as the +*create_salted_verification_key()* function, accept optional arguments +to specify which hashing algorithm and prime number arguments should +be used during the authentication process. These options may be used +to tune the security/performance tradeoff for an application. +Generally speaking, specifying arguments with a higher number of bits +will result in a greater level of security. However, it will come at +the cost of increased computation time. The default values of SHA1 +hashes and 2048 bit prime numbers strike a good balance between +performance and security. These values should be sufficient for most +applications. Regardless of which values are used, the parameters +passed to the *User* and *Verifier* constructors must exactly match +those passed to *create_salted_verification_key()* + + +.. _constants: + +Constants +--------- + +.. table:: Hashing Algorithm Constants + +  ==============  ============== +  Hash Algorithm  Number of Bits +  ==============  ============== +  SHA1            160 +  SHA224          224 +  SHA256          256 +  SHA384          384 +  SHA512          512 +  ==============  ============== + +.. note:: + +  Larger hashing algorithms will result in larger session keys. + +.. table:: Prime Number Constants + +  ================= ============== +  Prime Number Size Number of Bits +  ================= ============== +  NG_1024           1024 +  NG_2048           2048 +  NG_4096           4096 +  NG_8192           8192 +  NG_CUSTOM         User Supplied +  ================= ============== + +.. note:: + +  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:: create_salted_verification_key ( username, password[, hash_alg=SHA1, ng_type=NG_2048, n_hex=None, g_hex=None] ) + +    *username* Name of the user + +    *password* Plaintext user password + +    *hash_alg*, *ng_type*, *n_hex*, *g_hex* Refer to the :ref:`constants` section. + +    Generate a salted verification key for the given username and password and return the tuple: +    (salt_bytes, verification_key_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_2048, n_hex=None, g_hex=None] ) + +  *username* Name of the remote user being authenticated. +   +  *bytes_s* Salt generated by :func:`create_salted_verification_key`. +   +  *bytes_v* Verification Key generated by :func:`create_salted_verification_key`. +   +  *bytes_A* Challenge from the remote user. Generated by +  :meth:`User.start_authentication`   + +  *hash_alg*, *ng_type*, *n_hex*, *g_hex* Refer to the :ref:`constants` section. +   +  .. method:: Verifier.authenticated() +   +    Return True if the authentication succeeded. False +    otherwise. +     +  .. method:: Verifier.get_username() +   +    Return the name of the user this :class:`Verifier` object is for. +     +  .. method:: Verifier.get_session_key() +   +    Return the session key for an authenticated user or None if the +    authentication failed or has not yet completed. +     +  .. method:: Verifier.get_challenge() +   +    Return (bytes_s, bytes_B) on success or (None, None) if +    authentication has failed. +     +  .. method:: Verifier.verify_session( user_M ) +   +    Complete 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 prove a user's identity to a remote :class:`Verifier` and +verifiy that the remote :class:`Verifier` knows the verification key associated with +the user's password. + +.. class:: User( username, password[, hash_alg=SHA1, ng_type=NG_2048, n_hex=None, g_hex=None] ) + +  *username* Name of the user being authenticated. +   +  *password* Password for the user. + +  *hash_alg*, *ng_type*, *n_hex*, *g_hex* Refer to the :ref:`constants` section. +     +  .. method:: User.authenticated() +   +    Return True if authentication succeeded. False +    otherwise. +     +  .. method:: User.get_username() +   +    Return the username passed to the constructor. +     +  .. method:: User.get_session_key() +   +    Return the session key if authentication succeeded or None if the +    authentication failed or has not yet completed. +     +  .. method:: User.start_authentication() +   +    Return (username, bytes_A). These should be passed to the +    constructor of the remote :class:`Verifer` +     +  .. method:: User.process_challenge( bytes_s, bytes_B ) +   +    Processe 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 ) +   +    Complete the :class:`User` side of the authentication process. By +    verifying the *bytes_H_AMK* value returned by +    :meth:`Verifier.verify_session`.  If the authentication succeded +    :meth:`authenticated` will return True +     +.. _example: + +Example +------- + +Simple Usage Example:: + +    import srp +     +    # The salt and verifier returned from srp.create_salted_verification_key() should be +    # stored on the server. +    salt, vkey = srp.create_salted_verification_key( 'testuser', 'testpassword' ) + +    class AuthenticationFailed (Exception): +        pass +     +    # ~~~ 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, vkey, A ) +    s,B      = svr.get_challenge() + +    if s is None or B is None: +        raise AuthenticationFailed() +     +    # Server => Client: s, B +    M        = usr.process_challenge( s, B ) + +    if M is None: +        raise AuthenticationFailed() +     +    # Client => Server: M +    HAMK     = svr.verify_session( M ) + +    if HAMK is None: +        raise AuthenticationFailed() +         +    # Server => Client: HAMK +    usr.verify_session( HAMK ) +     +    # At this point the authentication process is complete. +     +    assert usr.authenticated() +    assert svr.authenticated() + + + +Implementation Notes +-------------------- + +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. + + +.. _protocol-description: + +SRP 6a Protocol Description +--------------------------- + +The original SRP protocol, known as SRP-3, is defined in +RFC 2945. This implementation, however, uses SRP-6a which is a slight +improvement over SRP-3.  The authoritative definition for the SRP-6a +protocol is available at http://srp.stanford.edu. An additional +resource is RFC 5054 which covers the integration of SRP into +TLS. This RFC is the source of hashing strategy and the predefined N +and g constants used in this implementation. + +The following is a complete description of the SRP-6a protocol as implemented by +this library. Note that the ^ symbol indicates exponentiaion and the | symbol +indicates concatenation. + +.. rubric:: Primary Variables used in SRP 6a + +========= ================================================================= +Variables Description +========= ================================================================= +N         A large, safe prime (N = 2q+1, where q is a Sophie Germain prime) +          All arithmetic is performed in the field of integers modulo N +g         A generator modulo N +s         Small salt for the verification key  +I         Username +p         Cleartext password +H()       One-way hash function +a,b       Secret, random values +K         Session key +========= ================================================================= +    + +.. rubric:: Derived Values used in SRP 6a + +======================================  ==================================== +Derived Values                          Description +======================================  ==================================== +k = H(N,g)                              Multiplier Parameter        +A = g^a                                 Public ephemeral value +B = kv + g^b                            Public ephemeral value +x = H(s, H( I | ':' | p ))              Private key (as defined by RFC 5054) +v = g^x                                 Password verifier +u = H(A,B)                              Random scrambling parameter +M = H(H(N) xor H(g), H(I), s, A, B, K)  Session key verifier +======================================  ==================================== + + +.. rubric:: Protocol Description + +The server stores the password verifier *v*. Authentication begins with a  +message from the client:: + +    client -> server: I, A = g^a +     +The server replies with the verifier salt and challenge:: + +    server -> client: s, B = kv + g^b + +At this point, both the client and server calculate the shared session key:: + +     client & server: u = H(A,B) +      +::    + +              server: K = H( (Av^u) ^ b ) +               +:: + +              client: x = H( s, H( I + ':' + p ) )             +              client: K = H( (B - kg^x) ^ (a + ux) ) + +Now both parties have a shared, strong session key *K*. To complete  +authentication they need to prove to each other that their keys match:: + +    client -> server: M = H(H(N) xor H(g), H(I), s, A, B, K) +    server -> client: H(A, M, K) +     +SRP 6a requires the two parties to use the following safeguards: + +1. The client will abort if it recieves B == 0 (mod N) or u == 0 +2. The server will abort if it detects A == 0 (mod N) +3. The client must show its proof of K first. If the server detects that this +   proof is incorrect it must abort without showing its own proof of K + | 
