diff options
| author | Eli Collins <elic@assurancetechnologies.com> | 2011-06-01 12:58:09 -0400 |
|---|---|---|
| committer | Eli Collins <elic@assurancetechnologies.com> | 2011-06-01 12:58:09 -0400 |
| commit | 92f3982bbcc94fae90794da52844f5b4f62d942f (patch) | |
| tree | d00fc46240d99c3d95ded6aa351c1f8da7c85ac4 | |
| parent | 0365e4aba1c3e3af42b7aca1e9ece96b7dbf9c36 (diff) | |
| download | passlib-92f3982bbcc94fae90794da52844f5b4f62d942f.tar.gz | |
various documentation updates
| -rw-r--r-- | docs/install.rst | 7 | ||||
| -rw-r--r-- | docs/lib/passlib.hash.bsdi_crypt.rst | 6 | ||||
| -rw-r--r-- | docs/lib/passlib.hash.des_crypt.rst | 7 | ||||
| -rw-r--r-- | docs/lib/passlib.hash.oracle10.rst | 6 | ||||
| -rw-r--r-- | docs/lib/passlib.hash.oracle11.rst | 2 | ||||
| -rw-r--r-- | docs/lib/passlib.hash.pbkdf2_digest.rst | 2 | ||||
| -rw-r--r-- | docs/lib/passlib.hash.rst | 6 | ||||
| -rw-r--r-- | docs/lib/passlib.hash.sha512_crypt.rst | 2 | ||||
| -rw-r--r-- | docs/lib/passlib.utils.handlers.rst | 26 | ||||
| -rw-r--r-- | docs/modular_crypt_format.rst | 10 | ||||
| -rw-r--r-- | docs/password_hash_api.rst | 47 | ||||
| -rw-r--r-- | passlib/registry.py | 22 |
12 files changed, 89 insertions, 54 deletions
diff --git a/docs/install.rst b/docs/install.rst index f95a494..ff267cb 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -11,8 +11,7 @@ Requirements Python 3.x is not yet supported, work is `ongoing <http://code.google.com/p/passlib/issues/detail?id=1>`_. - Passlib is pure-python, and should be useable on all platforms - (eg CPython, PyPy, and Jython). + Passlib is pure-python, and should support all available Python implementations and platforms. * `py-bcrypt <http://www.mindrot.org/projects/py-bcrypt/>`_ (optional) @@ -57,6 +56,10 @@ Once PassLib and Nose have been installed, the tests may be run from the source # to run all tests... PASSLIB_TESTS="all" nosetests -v passlib/tests + # to run nose with the optional coverage plugin... + PASSLIB_TESTS="all" nosetests -v passlib/tests --with-coverage \ + --cover-package=passlib --cover-html --cover-html-dir build/coverage + Documentation ============= The latest copy of this documentation should always be available diff --git a/docs/lib/passlib.hash.bsdi_crypt.rst b/docs/lib/passlib.hash.bsdi_crypt.rst index 2ef5df0..bd2d334 100644 --- a/docs/lib/passlib.hash.bsdi_crypt.rst +++ b/docs/lib/passlib.hash.bsdi_crypt.rst @@ -67,7 +67,7 @@ The checksum is formed by a modified version of the DES cipher in encrypt mode: The salt string uses little-endian :func:`hash64 <passlib.utils.h64.decode_int24>` encoding. -4. The password is NULL-padded on the end to the smallests non-zero multiple of 8 bytes. +4. The password is NULL-padded on the end to the smallest non-zero multiple of 8 bytes. 5. The lower 7 bits of the first 8 bytes of the password are used to form a 56-bit integer; with the first byte providing @@ -81,7 +81,7 @@ The checksum is formed by a modified version of the DES cipher in encrypt mode: b. Step 5 is repeated for the current 8-byte block, and xored against the existing DES key. -7. Repeated rounds of modified DES encryption are performed; +7. Repeated rounds of (modified) DES encryption are performed; starting with a null input block, and using the 56-bit integer from step 5/6 as the DES key. @@ -89,7 +89,7 @@ The checksum is formed by a modified version of the DES cipher in encrypt mode: by swapping bits :samp:`{i}` and :samp:`{i}+24` in the DES E-Box output if and only if bit :samp:`{i}` is set in the salt value. - The number of rounds to is controlled by the value decoded in step 2. + The number of rounds is controlled by the value decoded in step 2. 8. The 64-bit result of the last round of step 7 is then lsb-padded with 2 zero bits. diff --git a/docs/lib/passlib.hash.des_crypt.rst b/docs/lib/passlib.hash.des_crypt.rst index 4855e9a..5893da4 100644 --- a/docs/lib/passlib.hash.des_crypt.rst +++ b/docs/lib/passlib.hash.des_crypt.rst @@ -105,9 +105,10 @@ This implementation of des-crypt differs from others in a few ways: * Minimum salt string: - Some implementations of des-crypt allow empty and single-character salt strings. - However, the behavior in these cases varies wildly between implementations, - including errors and broken hashes. + Some implementations of des-crypt permit empty and single-character salt strings. + However, behavior in these cases varies wildly; + with implementations returning everything from errors + to incorrect hashes that never validate. To avoid all this, PassLib will throw an "invalid salt" if the provided salt string is not at least 2 characters. diff --git a/docs/lib/passlib.hash.oracle10.rst b/docs/lib/passlib.hash.oracle10.rst index d5bb113..a276a0f 100644 --- a/docs/lib/passlib.hash.oracle10.rst +++ b/docs/lib/passlib.hash.oracle10.rst @@ -76,7 +76,7 @@ Oracle10 hashes can be formed by the following procedure: Security Issues =============== This algorithm it not suitable for *any* use besides manipulating existing -Oracle10 account passwords, due to the following flaws: +Oracle10 account passwords, due to the following flaws [#flaws]: * It's use of the username as a salt value means that common usernames (eg ``system``) will occur more frequently as salts, @@ -112,5 +112,9 @@ References PassLib uses ``utf-16-be``, as this is both compatible with existing test vectors and supports unicode input. +.. [#flaws] Whitepaper analyzing flaws in this algorithm - + `<http://www.isg.rhul.ac.uk/~ccid/publications/oracle_passwd.pdf>`_. + .. [#] Description of Oracle10g and Oracle11g algorithms - `<http://www.notesbit.com/index.php/scripts-oracle/oracle-11g-new-password-algorithm-is-revealed-by-seclistsorg/>`_. + diff --git a/docs/lib/passlib.hash.oracle11.rst b/docs/lib/passlib.hash.oracle11.rst index 84e6ee6..09fef12 100644 --- a/docs/lib/passlib.hash.oracle11.rst +++ b/docs/lib/passlib.hash.oracle11.rst @@ -44,7 +44,7 @@ Format & Algorithm ================== An example oracle11 hash (of the string ``password``) is: - ``'S:4143053633E59B4992A8EA17D2FF542C9EDEB335C886EED9C80450C1B4E6'`` + ``S:4143053633E59B4992A8EA17D2FF542C9EDEB335C886EED9C80450C1B4E6`` An oracle11 hash string has the format :samp:`S:{checksum}{salt}`, where: diff --git a/docs/lib/passlib.hash.pbkdf2_digest.rst b/docs/lib/passlib.hash.pbkdf2_digest.rst index a87a338..64c9b3a 100644 --- a/docs/lib/passlib.hash.pbkdf2_digest.rst +++ b/docs/lib/passlib.hash.pbkdf2_digest.rst @@ -42,6 +42,8 @@ Interface .. autoclass:: pbkdf2_sha512() +.. _mcf-pbkdf2-format: + Format & Algorithm ================== An example :class:`!pbkdf2_sha256` hash (of ``password``):: diff --git a/docs/lib/passlib.hash.rst b/docs/lib/passlib.hash.rst index 4824b6a..7855ac3 100644 --- a/docs/lib/passlib.hash.rst +++ b/docs/lib/passlib.hash.rst @@ -144,8 +144,8 @@ but follow the LDAP format: passlib.hash.ldap_other -* :class:`ldap_hex_md5` - Hex-encoded MD5 Digest -* :class:`ldap_hex_sha1` - Hex-encoded SHA1 Digest +* :class:`passlib.hash.ldap_hex_md5` - Hex-encoded MD5 Digest +* :class:`passlib.hash.ldap_hex_sha1` - Hex-encoded SHA1 Digest .. toctree:: :maxdepth: 1 @@ -153,7 +153,7 @@ but follow the LDAP format: passlib.hash.ldap_pbkdf2_digest passlib.hash.atlassian_pbkdf2_sha1 -* :class:`roundup_plaintext` - Roundup-specific LDAP Plaintext Handler +* :class:`passlib.hash.roundup_plaintext` - Roundup-specific LDAP Plaintext Handler .. _database-hashes: diff --git a/docs/lib/passlib.hash.sha512_crypt.rst b/docs/lib/passlib.hash.sha512_crypt.rst index a5c63d5..86378ea 100644 --- a/docs/lib/passlib.hash.sha512_crypt.rst +++ b/docs/lib/passlib.hash.sha512_crypt.rst @@ -4,7 +4,7 @@ .. currentmodule:: passlib.hash -SHA-512 Crypt and SHA-256 Crypt were developed in 2008 by Ulrich Drepper +SHA-512 Crypt and SHA-256 Crypt were developed in 2008 by Ulrich Drepper [#f1]_ as a successor to :class:`~passlib.hash.md5_crypt`. They includes fixes and advancements such as variable rounds, and use of NIST-approved cryptgraphic primitives. SHA-256 / SHA-512 Crypt are currently the default password hash for many systems diff --git a/docs/lib/passlib.utils.handlers.rst b/docs/lib/passlib.utils.handlers.rst index c35a589..4670fe7 100644 --- a/docs/lib/passlib.utils.handlers.rst +++ b/docs/lib/passlib.utils.handlers.rst @@ -43,12 +43,12 @@ Most of the handlers built into PassLib are based around the :class:`GenericHand class. This class is designed under the assumption that the common workflow for hashes is some combination of the following: -1. parse hash into constituent parts - performed by :meth:`GenericHandler.from_string`. +1. parse hash into constituent parts - performed by :meth:`~GenericHandler.from_string`. 2. validate constituent parts - performed by :class:`!GenericHandler`'s constructor, - add the normalization functions such as :meth:`norm_checksum` and :meth:`norm_salt` + and the normalization functions such as :meth:`~GenericHandler.norm_checksum` and :meth:`~HasSalt.norm_salt` which are provided by it's related mixin classes. -3. calculate the raw checksum for a specific password - performed by :meth:`GenericHandler.calc_checksum`. -4. assemble hash, including new checksum, into a new string - performed by :meth:`GenericHandler.to_string`. +3. calculate the raw checksum for a specific password - performed by :meth:`~GenericHandler.calc_checksum`. +4. assemble hash, including new checksum, into a new string - performed by :meth:`~GenericHandler.to_string`. With this in mind, :class:`!GenericHandler` provides implementations of most of the :ref:`password-hash-api` methods, eliminating the need @@ -92,16 +92,18 @@ In order to use :class:`!GenericHandler`, just subclass it, and then do the foll Some additional notes: - * In addition to simple subclassing :class:`!GenericHandler`, most handlers + * In addition to simply subclassing :class:`!GenericHandler`, most handlers will also benefit from adding in some of the mixin classes that are designed to add features to :class:`!GenericHandler`. See :ref:`generic-handler-mixins` for more details. - * Most implementations will want to optimize the behavior of the default :meth:`identify` method. - If left alone, it will identify any hash which :meth:`from_string` does not raise :exc:`ValueError` for. - For faster identification purposes, subclasses may fill in the :attr:`ident` attribute - with the hash's identifying prefix, which :meth:`identify` will then be use instead. - For more complex situations, a custom implementation can be provided, though + * Most implementations will want to alter/override the default :meth:`~GenericHandler.identify` method. + By default, it returns ``True`` for all hashes that :meth:`~GenericHandler.from_string` + can parse without raising a :exc:`ValueError`; which is reliable, but somewhat slow. + For faster identification purposes, subclasses may fill in the :attr:`~GenericHandler.ident` attribute + with the hash's identifying prefix, which :meth:`~GenericHandler.identify` will then test for + instead of calling :meth:`~GenericHandler.from_string`. + For more complex situations, a custom implementation should be used; the :class:`HasManyIdents` mixin may also be helpful. * This class does not support context kwds of any type, @@ -140,12 +142,12 @@ The StaticHandler class .. index:: pair: custom hash handler; testing -.. _testing-hash-handlers: - Other Constructors ================== .. autoclass:: PrefixWrapper +.. _testing-hash-handlers: + Testing Hash Handlers ===================== Within it's unittests, Passlib provides the :class:`~passlib.tests.utils.HandlerCase` class, diff --git a/docs/modular_crypt_format.rst b/docs/modular_crypt_format.rst index aa80900..f22a8d9 100644 --- a/docs/modular_crypt_format.rst +++ b/docs/modular_crypt_format.rst @@ -16,11 +16,11 @@ have the format :samp:`${identifier}${content}`; where :samp:`{identifier}` is an short alphanumeric string uniquely identifying a particular scheme, and :samp:`{content}` is the contents of the scheme, using only the characters -``[a-zA-Z0-9./]``. +in the regexp range ``[a-zA-Z0-9./]``. -However, there appears to be no actual rules, specification document, -or central registry of identifiers; so the modular -crypt format is more of an ad-hoc idea than a true standard. +However, there appears to be no central registry of identifiers, +no specification document, and no actual rules; +so the modular crypt format is more of an ad-hoc idea rather than a true standard. History ======= @@ -147,7 +147,7 @@ Scheme Prefix Known Uses =========================================== =================== =========================== :class:`~passlib.hash.apr_md5_crypt` ``$apr1$`` Apache htdigest files :class:`~passlib.hash.phpass` ``$P$``, ``$H$`` PHPass-based applications -:class:`~passlib.hash.pbkdf2_sha1` ``$pbkdf2-sha1$`` +:class:`~passlib.hash.pbkdf2_sha1` ``$pbkdf2$`` :class:`~passlib.hash.pbkdf2_sha256` ``$pbkdf2-sha256$`` :class:`~passlib.hash.pbkdf2_sha512` ``$pbkdf2-sha512$`` :class:`~passlib.hash.dlitz_pbkdf2_sha1` ``$p5k2$`` diff --git a/docs/password_hash_api.rst b/docs/password_hash_api.rst index 609b8c2..7b9e167 100644 --- a/docs/password_hash_api.rst +++ b/docs/password_hash_api.rst @@ -15,7 +15,7 @@ Overview All of the hashes supported by PassLib are implemented using classes [#otypes]_ which support an identical interface; this document describes that interface in terms of a non-existent abstract class called :class:`!PasswordHash`. -All of the supported password hashes [#supported]_ expose (at a minimum) the following: +All of the supported password hashes [#supported]_ provide the following methods and attributes: :ref:`required-attributes` @@ -34,7 +34,7 @@ All of the supported password hashes [#supported]_ expose (at a minimum) the fol This interface consists of the :meth:`~PasswordHash.genconfig` and :meth:`~PasswordHash.genhash` classmethods. - This mimics the standard unix crypt interface, + These methods mimic the standard unix crypt interface, and are not usually needed by applications. :ref:`optional-attributes` @@ -114,16 +114,19 @@ Required Attributes ``salt`` If present, this means the algorithm contains some number of bits of salt - which should vary with every new hash created. + which should vary with every new hash created. - Providing this as a keyword should allow the application to select - a specific salt string; though not only is this far from needed - for most cases, the salt string's content constraints vary for each algorithm. + Additionally, this means + :meth:`~PasswordHash.genconfig` and :meth:`~PasswordHash.encrypt` + should both accept an optional ``salt`` keyword allowing the user + to specify a bare salt string. Note that this feature is rarely + needed, and the constraints on the size & content of this string + will vary for each algorithm. ``salt_size`` - If present, this means the algorithm will auto-generate a salt - of the specified number of characters - (assuming ``salt`` is not specified explicitly). + Most algorithms which support ``salt`` will auto-generate a salt string + if none is provided. If this keyword is also present, it means it + can be used to select the size of the auto-generated salt. If omitted, most algorithms will fall back to a default salt size. ``rounds`` @@ -150,7 +153,7 @@ Required Attributes Some algorithms require external contextual information in order to generate a checksum for a password. An example of this is :doc:`Postgres' MD5 algorithm <lib/passlib.hash.postgres_md5>`, - which requires the username to be provided when generating a hash + which requires the username be provided when generating a hash (see that class for an example of how this works in pratice). Since most password hashes require no external information, @@ -227,10 +230,16 @@ which scheme a hash belongs to when multiple schemes are in use. .. note:: - Some handlers may or may not return ``True`` for malformed hashes. - Those that do will raise a ValueError once the hash is passed to :meth:`~PasswordHash.verify`. - Most handlers, however, will just return ``False``. - + The goal of this method is positively identify the correct + handler for a given hash, and do it as efficiently as possible. + In order to accomplish this, many implementations perform only minimal + validation of the candidate hashes. Thus, they may return ``True`` + for hashes which are identifiable, but malformed enough that + a :exc:`ValueError` when the string is passed to + :func:`~PasswordHash.verify` or :func:`~PasswordHash.genhash`. + Because of this, applications should rely on this method only for identification, + not confirmation that a hash is correctly formed. + .. classmethod:: PasswordHash.verify(secret, hash, \*\*context_kwds) verify a secret against an existing hash. @@ -365,7 +374,7 @@ across all handlers in passlib. .. todo:: Consider making these attributes required for all hashes - which support the appropriate :attr:`settings` keyword. + which support the appropriate keyword in :attr:`~PasswordHash.setting_kwds`. .. _optional-rounds-attributes: @@ -428,22 +437,22 @@ the following attributes are usually exposed. .. attribute:: PasswordHash.min_salt_size - minimum number of characters required in salt string, - if provided to :meth:`~PasswordHash.genconfig` or :meth:`~PasswordHash.encrypt`. + minimum number of characters required for any salt string + provided to :meth:`~PasswordHash.genconfig` or :meth:`~PasswordHash.encrypt`. must be an integer within ``range(0,max_salt_size+1)``. .. attribute:: PasswordHash.default_salt_size size of salts generated by genconfig when no salt is provided by caller. - for most hashes, this defaults to :attr:`!PasswordHash.max_salt_size`. + for most hashes, this defaults to :attr:`~PasswordHash.max_salt_size`. this value must be within ``range(min_salt_size, max_salt_size+1)``. .. attribute:: PasswordHash.salt_chars string containing list of all characters which are allowed to be specified in salt parameter. - for most hashes, this is equal to `passlib.utils.h64.CHARS`. + for most hashes, this is equal to :data:`passlib.utils.h64.CHARS`. .. warning:: diff --git a/passlib/registry.py b/passlib/registry.py index 46e38a6..8de7716 100644 --- a/passlib/registry.py +++ b/passlib/registry.py @@ -149,8 +149,19 @@ def register_crypt_handler_path(name, path): :arg path: module import path the specified module path should contain a password hash handler - called :samp:`{name}`, or the path may contain a semicolon, + called :samp:`{name}`, or the path may contain a colon, specifying the module and module attribute to use. + for example, the following would cause ``get_handler("myhash")`` to look + for a class named ``myhash`` within the ``myapp.helpers`` module:: + + >>> from passlib.registry import registry_crypt_handler_path + >>> registry_crypt_handler_path("myhash", "myapp.helpers") + + ...while this form would cause ``get_handler("myhash")`` to look + for a class name ``MyHash`` within the ``myapp.helpers`` module:: + + >>> from passlib.registry import registry_crypt_handler_path + >>> registry_crypt_handler_path("myhash", "myapp.helpers:MyHash") """ global _handler_locations if ':' in path: @@ -167,6 +178,9 @@ def register_crypt_handler(handler, force=False, name=None): :arg handler: the password hash handler to register :param force: force override of existing handler (defaults to False) + :param name: + [internal kwd] if specified, ensures ``handler.name`` + matches this value, or raises :exc:`ValueError`. :raises TypeError: if the specified object does not appear to be a valid handler. @@ -228,11 +242,11 @@ def get_crypt_handler(name, default=Undef): it checks if the location is known, and loads it first. :arg name: name of handler to return - :param default: if specified, returns default value if no handler found. + :param default: optional default value to return if no handler with specified name is found. - :raises KeyError: if no handler matching that name is found, and no default specified + :raises KeyError: if no handler matching that name is found, and no default specified, a KeyError will be raised. - :returns: handler attached to name, or default if specified + :returns: handler attached to name, or default value (if specified). """ global _handlers, _handler_locations |
