diff options
author | Eli Collins <elic@assurancetechnologies.com> | 2011-03-14 21:21:42 -0400 |
---|---|---|
committer | Eli Collins <elic@assurancetechnologies.com> | 2011-03-14 21:21:42 -0400 |
commit | 1d0a05a785795bd85708d49c7dfa27fbaf4a03c7 (patch) | |
tree | 783d458aed2a4f31422eecff3949ddf7b5e5f307 /docs/password_hash_api.rst | |
parent | 5076cf146f56122ed712f17849dfbc782ca36e93 (diff) | |
download | passlib-1d0a05a785795bd85708d49c7dfa27fbaf4a03c7.tar.gz |
documentation work
==================
* finished password hash api description
* various documentation cleanups
* removed unused quickstart doc
Diffstat (limited to 'docs/password_hash_api.rst')
-rw-r--r-- | docs/password_hash_api.rst | 307 |
1 files changed, 185 insertions, 122 deletions
diff --git a/docs/password_hash_api.rst b/docs/password_hash_api.rst index 97a6798..1c3f6ab 100644 --- a/docs/password_hash_api.rst +++ b/docs/password_hash_api.rst @@ -1,110 +1,157 @@ .. _password-hash-api: -====================== +================= Password Hash API -====================== - -Motivation -========== -Passlib supports many different password hashing schemes. -A majority of them were originally designed to be used on a unix -system, follow some variant of the unix ``crypt()`` api, -and have are encoded using the :ref:`modular-crypt-format`. -Others were designed for use specific contexts only, -such as PostgreSQL. - -Passlib was designed to provide a uniform interface to implementations -of all these schemes, as well as hide away as much of the implementation -detail as possible; both in order to make it easier to integrate password hashing -into new and existing applications. Because of these goals, some of the methods -required by the crypt handler api tend to overlap slightly, -in order to accomodate a wide variety of application requirements, -and other parts have been kept intentionally non-commital, in order to allow -flexibility of implementation. - -All of the schemes built into passlib implement this interface; -most them as modules within the :mod:`passlib.hash` package. +================= Overview ======== -A handler which implements a password hash may be a module, class, or instance -(though most of the ones builtin to Passlib are classes). -The only requirement is that it expose a minimum of the following attributes -and functions (for classes, the following functions must be static or class methods). - -All handlers have the following three attributes: - - * ``name`` - unique identifier used to distinguish scheme within - * ``setting_kwds`` - list of settings recognized by ``genconfig()`` and ``encrypt()``. - * ``context_kwds`` - list of context specified keywords required by algorithm - -All handlers have the following five functions: - - * ``encrypt(secret, **context_and_settings) -> hash`` - used for encrypting secret using specified options - * ``identify(hash) -> True|False`` - used for identifying hash belonging to this algorithm - * ``verify(secret, hash, **context)`` - used for verifying a secret against an existing hash - - * ``genconfig(**settings) -> configuration string`` - used for generating configuration strings. - * ``genhash(secret, config, **context) -> hash`` - used for encrypting secret using configuration string or existing hash - -Usage Examples -============== - -.. todo:: - - show some quick examples using bcrypt. - -Informational Attributes -======================== -.. attribute:: name +All of the hashes supported by PassLib are implemented using classes +which support an identical interface; this document describes that +interface in terms of a non-existent abstract class called :class:`!PasswordHash`. +All of the :doc:`supported password hashes <lib/passlib.hash>` +expose (at a minimum) the following methods and attributes: + +The `required informational attributes`_ + These consist of the attributes :attr:`~PasswordHash.name`, + :attr:`~PasswordHash.setting_kwds`, and :attr:`~PasswordHash.context_kwds`. + They permit users and applications to detect what features a specific :class:`!PasswordHash` + allows and/or requires. + +The `application interface`_ + This consists of the :meth:`~PasswordHash.encrypt`, + :meth:`~PasswordHash.identify`, and :meth:`~PasswordHash.verify` classmethods. + Most applications will only need to make use of these methods. + +The `crypt interface`_ + This consists of the :meth:`~PasswordHash.genconfig`, + :meth:`~PasswordHash.genhash`. This mimics the standard unix crypt interface, + but is usually used directly by applications. + +The `optional informational attributes`_ + These attributes provide additional information + about the capabilities and limitations of certain password hash schemes. + +Usage +===== +While most uses of PassLib are done through a :class:`~passlib.base.CryptContext` class, +the various :class:`!PasswordHash` classes can be used directly to manipulate +passwords: + + >>> # for example, the SHA256-Crypt class: + >>> from passlib.hash import sha256_crypt as sc + + >>> # using it to encrypt a password: + >>> h = sc.encrypt("password") + >>> h + '$5$rounds=40000$HIo6SCnVL9zqF8TK$y2sUnu13gp4cv0YgLQMW56PfQjWaTyiHjVbXTgleYG9' + + >>> # subsequent calls to sc.encrypt() will generate a new salt: + >>> sc.encrypt("password") + '$5$rounds=40000$1JfxoiYM5Pxokyh8$ez8uV8jjXW7SjpaTg2vHJmx3Qn36uyZpjhyC9AfBi7B' + + >>> # the same, but with an explict number of rounds: + >>> sc.encrypt("password", rounds=10000) + '$5$rounds=10000$UkvoKJb8BPrLnR.D$OrUnOdr.IJx74hmyyzuRdr5k9lSXdkFxKmr7bLQTty5' + + >>> #the identify method can be used to determine the format of an unknown hash: + >>> sc.identify(h) + True + + >>> #check if some other hash is recognized (in this case, an MD5-Crypt hash) + >>> sc.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31') + False + + >>> #the verify method encapsulates all hash comparison logic for a class: + >>> sc.verify("password", h) + True + >>> sc.verify("wrongpassword", h) + False + +.. _required-informational-attributes: + +Required Informational Attributes +================================= +.. attribute:: PasswordHash.name A unique name used to identify - the particular algorithm this handler implements. + the particular scheme this class implements. - These names should consist only of lowercase a-z, the digits 0-9, and hyphens. + These names should consist only of lowercase a-z, the digits 0-9, and underscores. .. note:: - All handlers built into passlib are implemented as modules - whose path corresponds to the name, with an underscore replacing the hyphen. - For example, ``des-crypt`` is stored as the module ``passlib.hash.des_crypt``. + All handlers built into passlib are implemented as classes + located under :samp:`passlib.hash.{name}`, where :samp:`{name}` + is both the class name, and the value of the ``name`` attribute. + This is not a requirement, and may not be true for externally-defined handers. -.. attribute:: setting_kwds +.. attribute:: PasswordHash.setting_kwds - If the algorithm supports per-hash configuration + If the scheme supports per-hash configuration (such as salts, variable rounds, etc), this attribute should contain a tuple of keywords corresponding to each of those configuration options. - This should correspond with the keywords accepted - by :func:`genconfig`, see that method for details. + This should list all the main configuration keywords accepted + by :meth:`~PasswordHash.genconfig` and :meth:`~PasswordHash.encrypt`. - If no settings are supported, this attribute - is an empty tuple. + If no configuration options are supported, this attribute should be an empty tuple. -.. attribute:: context_kwds + While each class may support a variety of options, each with their own meaning + and semantics, the following keywords should have the same behavior + across all schemes: - Some algorithms require external contextual information - in order to generate a checksum for a password. - An example of this is Postgres' md5 algorithm, - which requires the username to be provided - (which it uses as a salt). + ``salt`` + If present, this means the algorithm contains some number of bits of salt + 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. + + ``rounds`` + If present, this means the algorithm allows for a variable number of rounds + to be used, allowing the processor time required to be increased. + + Providing this as a keyword should allow the application to + override the class' default number of rounds. While this + must be a non-negative integer for all implementations, + additional constraints may be present for each algorith + (such as the cost varying on a linear or logarithmic scale). + + ``ident`` + If present, the class supports multiple formats for encoding + the same hash. The class's documentation will generally list + the allowed values, allowing alternate output formats to be selected. + +.. attribute:: PasswordHash.context_kwds This attribute should contain a tuple of keywords which should be passed into :func:`encrypt`, :func:`verify`, and :func:`genhash` in order to encrypt a password. + 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 + (see that class for an example of how this works in pratice). + Since most password hashes require no external information, - this tuple will usually be empty. + this tuple will usually be empty, and references + to context keywords can be ignored for all but a few classes. -Primary Interface -================= -The ``encrypt()``, ``identify()``, and ``verify()`` methods are designed -to provide an easy interface for applications to encrypt new passwords -and verify existing passwords, without having to deal with details such -as salt formats. +.. _application-interface: -.. function:: encrypt(secret, \*\*settings_and_context) +Application Interface +===================== +The :meth:`~PasswordHash.encrypt`, :meth:`~PasswordHash.identify`, and :meth:`~PasswordHash.verify` methods are designed +to provide an easy interface for applications. They allow encrypt new passwords +without having to deal with details such as salt generation, verifying +passwords without having to deal with hash comparison rules, and determining +which scheme a hash belongs to when multiple schemes are in use. + +.. classmethod:: PasswordHash.encrypt(secret, \*\*settings_and_context) encrypt secret, returning resulting hash string. @@ -115,12 +162,12 @@ as salt formats. but the common case is to encode into utf-8 before processing. - :param kwds: + :param settings_and_context: All other keywords are algorithm-specified, - and should be listed in :attr:`setting_kwds` - and :attr:`context_kwds`. + and should be listed in :attr:`~PasswordHash.setting_kwds` + and :attr:`~PasswordHash.context_kwds`. - Common keywords include ``salt`` and ``rounds``. + Common settings keywords include ``salt`` and ``rounds``. :raises ValueError: * if settings are invalid and not correctable. @@ -134,9 +181,9 @@ as salt formats. on the types of characters. :returns: - Hash encoded in algorithm-specified format. + Hash string, encoded in algorithm-specific format. -.. function:: identify(hash) +.. classmethod:: PasswordHash.identify(hash) identify if a hash string belongs to this algorithm. @@ -150,11 +197,12 @@ as salt formats. * ``False`` if none of the above conditions was met. .. 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 :func:`verify`. + Those that do will raise a ValueError once the hash is passed to :meth:`~PasswordHash.verify`. Most handlers, however, will just return ``False``. -.. function:: verify(secret, hash, \*\*context) +.. classmethod:: PasswordHash.verify(secret, hash, \*\*context) verify a secret against an existing hash. @@ -169,7 +217,7 @@ as salt formats. :param context: Any additional keywords will be passed to the encrypt method. These should be limited to those listed - in :attr:`context_kwds`. + in :attr:`~PasswordHash.context_kwds`. :raises TypeError: * if the secret is not a string. @@ -177,21 +225,24 @@ as salt formats. :raises ValueError: * if the hash not specified * if the hash does not match this algorithm's hash format - * if the provided secret contains forbidden chars (see :func:`encrypt`) + * if the provided secret contains forbidden characters (see :meth:`~PasswordHash.encrypt`) :returns: ``True`` if the secret matches, otherwise ``False``. -Secondary Interface -=================== +.. _crypt-interface: + +Crypt Interface +=============== While the primary interface is generally the most useful when integrating password support into an application, those methods are for the most part -built on top of the secondary interface, which is somewhat simpler +built on top of the crypt interface, which is somewhat simpler for *implementing* new password schemes. It also happens to match more closely with the crypt api of most unix systems, -and consists of two functions: ``genconfig()`` and ``genhash``. +and consists of two functions: :meth:`~PasswordHash.genconfig()`` +and :meth:`~PasswordHash.genhash()``. -.. function:: genconfig(\*\*settings) +.. classmethod:: PasswordHash.genconfig(\*\*settings) returns configuration string encoding settings for hash generation @@ -203,7 +254,7 @@ and consists of two functions: ``genconfig()`` and ``genhash``. than just a salt). This function takes in optional configuration options (a complete list - of which should be found in :attr:`setting_kwds`), validates + of which should be found in :attr:`~PasswordHash.setting_kwds`), validates the inputs, fills in defaults where appropriate, and returns a configuration string. @@ -229,7 +280,7 @@ and consists of two functions: ``genconfig()`` and ``genhash``. be clipped but accepted. :param settings: - this function takes in keywords as specified in :attr:`setting_kwds`. + this function takes in keywords as specified in :attr:`~PasswordHash.setting_kwds`. commonly supported keywords include ``salt`` and ``rounds``. :raises ValueError: @@ -242,7 +293,7 @@ and consists of two functions: ``genconfig()`` and ``genhash``. :returns: the configuration string, or ``None`` if the algorithm does not support any configuration options. -.. function:: genhash(secret, config, \*\*context) +.. classmethod:: PasswordHash.genhash(secret, config, \*\*context) encrypt secret to hash @@ -254,13 +305,13 @@ and consists of two functions: ``genconfig()`` and ``genhash``. :arg config: configuration string to use when encrypting secret. this can either be an existing hash that was previously - returned by :meth:`genhash`, or a configuration string - that was previously created by :meth:`genconfig`. + returned by :meth:`~PasswordHash.genhash`, or a configuration string + that was previously created by :meth:`~PasswordHash.genconfig`. :param context: All other keywords must be external contextual information required by the algorithm to create the hash. If any, - these kwds must be specified in :attr:`context_kwds`. + these kwds must be specified in :attr:`~PasswordHash.context_kwds`. :raises TypeError: * if the configuration string is not provided @@ -277,56 +328,68 @@ and consists of two functions: ``genconfig()`` and ``genhash``. Optional Informational Attributes ================================= Many of the handlers in passlib expose the following informational -attributes, though their presence and meaning is not uniform +attributes, though their presence is not uniform across all handlers in passlib. -For schemes which support a variable number of rounds, -the following attributes are usually exposed -(applications can test by checking for ``getattr(handler,"default_rounds",None)>0``): +.. todo:: -.. attribute:: default_rounds + could change these to be required if the appropriate setting kwd is used. + +Rounds Information +------------------ +For schemes which support a variable number of rounds (ie, ``'rounds' in PasswordHash.setting_kwds``), +the following attributes are usually exposed. +(Applications can test for this suites' presence by checking if ``getattr(handler,"max_rounds",None)>0``) + +.. attribute:: PasswordHash.default_rounds The default number of rounds that will be used if not - explicitly set when calling :func:`encrypt` or :func:`genconfig`. + explicitly set when calling :meth:`~PasswordHash.encrypt` or :meth:`~PasswordHash.genconfig`. -.. attribute:: min_rounds +.. attribute:: PasswordHash.min_rounds The minimum number of rounds the scheme allows. Specifying values below this will generally result - in a warning, and ``min_rounds`` will be used instead. + in a warning, and :attr:`~!PasswordHash.min_rounds` will be used instead. -.. attribute:: max_rounds +.. attribute:: PasswordHash.max_rounds The maximum number of rounds the scheme allows. Specifying values above this will generally result - in a warning, and ``max_rounds`` will be used instead. + in a warning, and :attr:`~!PasswordHash.max_rounds` will be used instead. -.. attribute:: rounds_cost +.. attribute:: PasswordHash.rounds_cost Specifies how the rounds value affects the amount of time taken. Currently used values are: - ``linear`` - time taken scales linearly with rounds value (eg: sha512_crypt) - ``log2`` - time taken scales exponentially with rounds value (eg: bcrypt) + ``linear`` + time taken scales linearly with rounds value (eg: :class:`~passlib.hash.sha512_crypt`) + + ``log2`` + time taken scales exponentially with rounds value (eg: :class:`~passlib.hash.bcrypt`) -For schemes which support a salt, -the following attributes are usually exposed -(applications can test by checking for ``getattr(handler,"max_salt_chars",None)>0``): +Salt Information +---------------- +For schemes which support a salt (ie, ``'salt' in PasswordHash.setting_kwds``), +the following attributes are usually exposed. +(Applications can test for this suites' presence by checking if ``getattr(handler,"max_salt_chars",None)>0``) -.. attribute:: max_salt_chars +.. attribute:: PasswordHash.max_salt_chars maximum number of characters which will be *used* - if a salt string is provided to :func:`genconfig` or :func:`encrypt`. + if a salt string is provided to :meth:`~PasswordHash.genconfig` or :meth:`~PasswordHash.encrypt`. must be positive integer if salts are supported, may be ``None`` or ``0`` if salts are not supported. -.. attribute:: min_salt_chars +.. attribute:: PasswordHash.min_salt_chars minimum number of characters required in salt string, - if provided to :func:`genconfig` or :func:`encrypt`. - must be non-negative integer. + if provided to :meth:`~PasswordHash.genconfig` or :meth:`~PasswordHash.encrypt`. + must be non-negative integer that is not greater than :attr:`~PasswordHash.max_salt_chars`. -.. attribute:: salt_charset +.. attribute:: PasswordHash.salt_charset string containing list of all characters which are allowed - to be specified in salt parameter. usually `passlib.utils.h64.CHARS`. + to be specified in salt parameter. + for most hashes, this is equal to `passlib.utils.h64.CHARS`. |