summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Collins <elic@assurancetechnologies.com>2011-03-24 16:25:18 -0400
committerEli Collins <elic@assurancetechnologies.com>2011-03-24 16:25:18 -0400
commit5796546d61fb580d1aa11f23de1aa6b326fb9e9b (patch)
tree1b6b3463117cceff4bcc5374137a0d8cf2cda0bc
parenteaadab04ad926174c39bcb161b3dd587c54228f8 (diff)
downloadpasslib-5796546d61fb580d1aa11f23de1aa6b326fb9e9b.tar.gz
documentation updates
===================== * CryptContext docs finished * README / LICENSE updated * license text changed to correct BSD wording * embarassingly, the history.rst is kinda off about release versions. tried to make it give readers better outline. * misc doc updates * some handler names (eg: 'context', 'all') now forbidden by register_crypt_handler() * bumped setup.cfg to b1
-rw-r--r--LICENSE69
-rw-r--r--README27
-rw-r--r--docs/contents.rst1
-rw-r--r--docs/copyright.rst91
-rw-r--r--docs/history.rst37
-rw-r--r--docs/index.rst25
-rw-r--r--docs/install.rst64
-rw-r--r--docs/lib/passlib.context-interface.rst9
-rw-r--r--docs/lib/passlib.context-options.rst266
-rw-r--r--docs/lib/passlib.context.rst26
-rw-r--r--passlib/context.py61
-rw-r--r--passlib/registry.py7
-rw-r--r--setup.cfg2
-rw-r--r--setup.py8
14 files changed, 456 insertions, 237 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d049276
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,69 @@
+License for PassLib
+===================
+Copyright (c) 2008-2011 by Assurance Technologies, LLC.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Licenses for incorporated software
+==================================
+PassLib contains some code derived from the following sources:
+
+jBcrypt
+-------
+Copyright (c) 2006 Damien Miller <djm@mindrot.org>
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+MD5-Crypt
+---------
+"THE BEER-WARE LICENSE" (Revision 42):
+<phk@login.dknet.dk> wrote this file. As long as you retain this notice you
+can do whatever you want with this stuff. If we meet some day, and you think
+this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
+
+UnixCrypt.java
+--------------
+UnixCrypt.java 0.9 96/11/25
+Copyright (c) 1996 Aki Yoshida. All rights reserved.
+Permission to use, copy, modify and distribute this software
+for non-commercial or commercial purposes and without fee is
+hereby granted provided that this copyright notice appears in
+all copies.
+
+modified April 2001
+by Iris Van den Broeke, Daniel Deville
+
+modified Aug 2005
+by Greg Wilkins (gregw)
diff --git a/README b/README
index 2eaea34..7e55ecf 100644
--- a/README
+++ b/README
@@ -1,13 +1,28 @@
+.. -*- restructuredtext -*-
+
==========================
The PassLib Python Library
==========================
+PassLib is a password hash library, which provides cross-platform
+implementations of over 20 password hashing algorithms; as well as a framework for managing
+and migrating existing password hashes. It's designed to be useful
+for any task from quickly verifying a hash found in /etc/shadow,
+to providing full-strength password hashing for multi-user application.
+
+The latest documentation can be found online `XXX`.
+
+Requirements
+-----------
+* Python 2.5 - 2.7
+* PyBCrypt (optional; if bcrypt support is needed)
+* M2Crypto (optional)
+
Installation
------------
-* For detailed installation instructions, see "docs/install.rst"
+To install from source using ``setup.py``::
+
+ python setup.py build
+ sudo python setup.py install
-Copyright & License
--------------------
-* (c) 2008-2011 - Assurance Technologies LLC
-* released under BSD license
-* For more license & copyright information, see "docs/copyright.rst"
+For more detailed installation & testing instructions, see "docs/install.rst",
diff --git a/docs/contents.rst b/docs/contents.rst
index 4912478..9331a9d 100644
--- a/docs/contents.rst
+++ b/docs/contents.rst
@@ -9,7 +9,6 @@ Table Of Contents
overview
lib/passlib.context
- lib/passlib.context-interface
lib/passlib.context-options
lib/passlib.apps
lib/passlib.apache
diff --git a/docs/copyright.rst b/docs/copyright.rst
index fbb22b4..23c160f 100644
--- a/docs/copyright.rst
+++ b/docs/copyright.rst
@@ -2,48 +2,45 @@
Copyrights & Licenses
=====================
-Copyright
-=========
-The PassLib library is (c) 2008-2011 `Assurance Technologies, LLC <http://www.assurancetechnologies.com>`_,
-excepting any code noted below as taken from :ref:`third party sources <third-party-software>`.
-Such portions are copyright their respective owners.
-
-License
-=======
-This library is released under the BSD license; we hope you find it useful.
-
-::
-
- The PassLib Python Library
-
- Copyright (c) 2008-2011 Assurance Technologies, LLC
-
- Permission to use, copy, modify, and distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-.. _third-party-software:
-
-Third Party Software
-====================
-PassLib contains some code taken from various third-party sources, which have their
-own licenses (all of which, it should be noted, are BSD-compatible).
-The following is a list of these sources, their owners, licenses, and the parts
-of PassLib derived from them.
+License for PassLib
+===================
+PassLib is available under the BSD license, and is (c) `Assurance Technologies <http://www.assurancetechnologies.com>`_::
+
+ Copyright (c) 2008-2011 by Assurance Technologies, LLC.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Licenses for incorporated software
+==================================
+PassLib contains some code derived from the following sources:
jBcrypt
-------
`jBCrypt <http://www.mindrot.org/projects/jBCrypt/>`_ is a pure-java
implementation of OpenBSD's BCrypt algorithm, written by Damien Miller,
-and released under a BSD license.
+and released under a BSD-like license.
:mod:`passlib.utils._slow_bcrypt` is a python translation of this code,
which is used as a fallback backend for :class:`passlib.hash.bcrypt`
@@ -68,10 +65,9 @@ This is the license and copyright for jBCrypt::
MD5-Crypt
---------
-The fallback pure-python implementation contained in :class:`passlib.hash.md5_crypt`
-was derived from the
-`FreeBSD md5-crypt <http://www.freebsd.org/cgi/cvsweb.cgi/~checkout~/src/lib/libcrypt/crypt.c?rev=1.2>`_,
-implementation which was released under the following license::
+The pure-python fallback used by :class:`passlib.hash.md5_crypt` was derived from the original
+`FreeBSD md5-crypt implementation <http://www.freebsd.org/cgi/cvsweb.cgi/~checkout~/src/lib/libcrypt/crypt.c?rev=1.2>`_,
+which is available under the following license::
"THE BEER-WARE LICENSE" (Revision 42):
<phk@login.dknet.dk> wrote this file. As long as you retain this notice you
@@ -80,16 +76,11 @@ implementation which was released under the following license::
UnixCrypt.java
--------------
-`UnixCrypt.java <http://www.dynamic.net.au/christos/crypt/UnixCrypt2.txt>`_
-is a pure-java implementation of the historic unix-crypt password hash algorithm.
+The DES utility functions in :mod:`passlib.utils.des` are derived
+from `UnixCrypt.java <http://www.dynamic.net.au/christos/crypt/UnixCrypt2.txt>`_,
+a pure-java implementation of the historic unix-crypt password hash algorithm.
Originally written by Aki Yoshida, and modified by others,
-it was released under a BSD-like license.
-
-The DES utility functions in :mod:`passlib.utils.des` are a descendant of
-this code, after being translated into python. (These are used for des-crypt,
-ext-des-crypt, and nthash support).
-
-This is the license and copyright for UnixCrypt.java::
+it is available under a BSD-like license::
UnixCrypt.java 0.9 96/11/25
Copyright (c) 1996 Aki Yoshida. All rights reserved.
diff --git a/docs/history.rst b/docs/history.rst
index 520666e..6cfc820 100644
--- a/docs/history.rst
+++ b/docs/history.rst
@@ -2,25 +2,36 @@
Release History
===============
-2011-01-10 -- version 1.0
+**1.3** (To Be Released)
+
* first public release
- * bugfixes
- * more documentation
+ * documentation completed
+ * 99% unittest coverage
+ * some refactoring and lots of bugfixes
+ * added support for a number of addtional password schemes:
+ bigcrypt, crypt16, sun md5 crypt, nthash, lmhash, oracle10 & 11,
+ phpass, sha1, generic hex digests, ldap digests.
+
+**1.2** (2011-01-06)
+
+ * many bugfixes
+ * global registry added
+ * transitional release for applications using BPS library.
+ * first truly functional release since splitting from BPS library (see below).
-2011-01-05 -- version 0.8
- * various code cleanups preparing for public release
- * bsdi-crypt, apr-md5-crypt, and other lesser known schemes added.
- * documentation added
+.. note::
-2009-03-10 -- version 0.7
- * postgres and mysql hash schemes added.
+ For all previous versions, PassLib did not exist independantly,
+ but as a subpackage of *BPS*, an private & unreleased toolkit library.
+
+**1.0** (2009-12-11)
-2008-10-02 -- version 0.6
* CryptContext & CryptHandler framework
+ * added support for: des-crypt, bcrypt (via pybcrypt), postgres, mysql
* added unit tests
- * added Unix-Crypt support and pure-python fallback
-2008-05-10 -- version 0.5
+**0.5** (2008-05-10)
+
* initial production version
* consolidated from code scattered across multiple applications
- * MD5-Crypt, SHA-256-Crypt, SHA-512-Crypt support
+ * MD5-Crypt, SHA256-Crypt, SHA512-Crypt support
diff --git a/docs/index.rst b/docs/index.rst
index 849df09..46cfc34 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -5,7 +5,7 @@ PassLib |release| documentation
Introduction
============
PassLib is a library for encrypting, verifying, and managing password hashes.
-It supports over 20 current and historical password hash schemes.
+It supports over 20 different password hash schemes.
It can be used for a variety of purposes:
* cross-platform replacement for stdlib's :func:`!crypt`.
@@ -21,8 +21,25 @@ It can be used for a variety of purposes:
Quick Links
===========
-* See the :doc:`Library Overview <overview>` for more details about passlib.
+.. raw:: html
-* See the :doc:`Installation Instructions <install>` to get PassLib installed on your system.
+ <table class="contentstable" align="center">
+ <tr>
+ <td width="50%" valign="top">
+ <p class="biglink">
+ <a class="biglink" href="overview.html">Library Overview</a><br>
+ <span class="linkdescr">describes how PassLib is laid out</span>
+ </p>
-* See the :mod:`passlib.hash <passlib.hash>` module for a complete list of supported hash algorithms.
+ <p class="biglink">
+ <a class="biglink" href="install.html">Installation</a><br>
+ <span class="linkdescr">requirements and installation instructions</span>
+ </p>
+
+ <p class="biglink">
+ <a class="biglink" href="lib/passlib.hash.html"><i>passlib.hash</i> module</a><br>
+ <span class="linkdescr">complete list of supported password hash algorithms</span>
+ </p>
+ </td>
+ </tr>
+ </table>
diff --git a/docs/install.rst b/docs/install.rst
index 64d8f30..8837e6f 100644
--- a/docs/install.rst
+++ b/docs/install.rst
@@ -4,56 +4,58 @@ Installation
Requirements
============
-PassLib currently has no external depedancies besides Python itself:
+* Python 2.5 - 2.7 is required.
- * Python 2.5 or better is required.
+ .. note::
- * PassLib has not been tested with Python 2.4 or earlier,
- and no guarantees are made about whether PassLib will work with them.
+ PassLib has not been tested with Python 2.4 or earlier,
+ and no guarantees are made about whether PassLib will work with those versions.
- * Python 3.x is **not** yet supported, work is ongoing.
+ .. note::
-The following libraries are not required, but will be used if found:
+ Python 3.x is **not** yet supported, work is ongoing.
- stdlib's :mod:`!crypt` module
+* `py-bcrypt <http://www.mindrot.org/projects/py-bcrypt/>`_ (optional)
- :func:`!crypt()` will be used if present, and if the host
- OS supports the specific scheme in question. OS support is autodetected
- for the following schemes: des-crypt, md5-crypt, bcrypt, sha256-crypt,
- and sha512-crypt.
+ If installed, pybcrypt will be used to support the BCrypt hash algorithm.
+ This is required if you want to handle BCrypt hashes,
+ and stdlib :mod:`!crypt` does not support BCrypt
+ (which is pretty much all non-BSD systems).
- `py-bcrypt <http://www.mindrot.org/projects/py-bcrypt/>`_
+* `M2Crypto <http://chandlerproject.org/bin/view/Projects/MeTooCrypto>`_ (optional)
- If installed, pybcrypt will be used to support the BCrypt hash algorithm.
- This is required if you want to handle BCrypt hashes,
- and stdlib :mod:`!crypt` does not support BCrypt
- (which is pretty much all non-BSD systems).
+ If installed, M2Crypto will be used to accelerate some
+ internal support functions, but it is not required.
- `M2Crypto <http://chandlerproject.org/bin/view/Projects/MeTooCrypto>`_
-
- If installed, M2Crypto will be used to accelerate some
- internal support functions, but it is not required.
-
-PassLib should be useable on all operating systems.
+PassLib is pure-python, and should be useable on all platforms.
Installing
==========
-PassLib can be installed with easy_install / pip, linked/copied into sys.path directly
-from it's source directory, or installed using :samp:`{$SOURCE}/setup.py install`,
-where :samp:`{$SOURCE}` is the path to the PassLib source directory.
-PassLib is pure python, there is nothing to compile or configure.
+To install from source directory using ``setup.py`` (requires Setuptools or Distribute)::
+
+ python setup.py build
+ sudo python setup.py install
+
+To install using easy_install::
+
+ easy_install passlib
+
+To install using pip::
+
+ pip install passlib
Testing
=======
PassLib contains a comprehensive set of unittests providing nearly complete coverage.
All unit tests are contained within the :mod:`passlib.tests` package,
and are designed to be run using the `Nose <http://somethingaboutorange.com/mrl/projects/nose>`_ unit testing library.
-Once PassLib and Nose have been installed::
- # to run the basic tests from the source directory...
+Once PassLib and Nose have been installed, the tests may be run from the source directory::
+
+ # to run the platform-relevant tests...
nosetests -v passlib/tests
- # to run ALL tests from the source directory...
+ # to run all tests...
PASSLIB_TESTS="all" nosetests -v passlib/tests
Documentation
@@ -68,7 +70,7 @@ you will need to:
* install `astdoc <http://www.assurancetechnologies.com/software/astdoc>`_ (a bundle of custom sphinx themes & extensions
used by Assurance Technologies).
* download the PassLib source
-* run :samp:`python {$SOURCE}/docs/make.py clean html` (where :samp:`{$SOURCE}` is the path to the PassLib source directory).
+* run :samp:`python docs/make.py clean html`.
-Once Sphinx completes it's run, point a web browser to the file at :samp:`{$SOURCE}/docs/_build/html/index.html`
+Once Sphinx completes it's run, point a web browser to the file at :samp:`docs/_build/html/index.html`
to access the PassLib documentation in html format.
diff --git a/docs/lib/passlib.context-interface.rst b/docs/lib/passlib.context-interface.rst
deleted file mode 100644
index e7689b2..0000000
--- a/docs/lib/passlib.context-interface.rst
+++ /dev/null
@@ -1,9 +0,0 @@
-===============================================
-:mod:`passlib.context` - CryptContext interface
-===============================================
-
-.. currentmodule:: passlib.context
-
-.. autoclass:: CryptContext(schemes=None, policy=<default policy>, \*\*kwds)
-
-.. autoclass:: CryptPolicy(\*\*kwds)
diff --git a/docs/lib/passlib.context-options.rst b/docs/lib/passlib.context-options.rst
index 24ddc72..1cf6000 100644
--- a/docs/lib/passlib.context-options.rst
+++ b/docs/lib/passlib.context-options.rst
@@ -1,124 +1,185 @@
+.. _cryptcontext-options:
+
=============================================
:mod:`passlib.context` - CryptContext options
=============================================
.. currentmodule:: passlib.context
-Context Configuration Policy
-============================
-.. warning::
+The :class:`CryptContext` accepts a number of keyword options.
+These are divides into the "context options", which affect
+the context instance directly, and the "hash options",
+which affect the context treats a particular type of hash:
- This section's writing and design are still very much in flux.
+Context Options
+===============
+The following keyword options are accepted by both the :class:`CryptContext`
+and :class:`CryptPolicy` constructors, and directly affect the behavior
+of the :class:`!CryptContext` instance itself:
-Each CryptContext instance is extremely configuration through a wide range
-of options. All of these options can be specified via the CryptContext
-constructor, or by loading the configuration of a section of an ini file
-(allowing an application's password policy to be specified externally).
+``schemes``
+ List of handler names and/or instances which the CryptContext should recognize.
+ This is usually required.
-All configuration options are stored in a CryptPolicy object,
-which can be created in the following ways:
+ For use in INI files, this may also be specified as a single comma-separated string
+ of handler names.
-* passing in options as keywords to it's constructor
-* loading options from a section of a :mod:`ConfigParser` ini file.
-* compositing together existing CryptPolicy objects (this allows for default policies, application policies, and run-time policies)
+ Any names specified must be registered globally with PassLib.
-Hash Configuration Options
-==========================
-Options for configuring a specific hash take the form of the name of
-``{name}.{option}`` (eg ``sha512_crypt.default_rounds``); where ``{name}`` is usually the name of a password hash,
-and ``{option}`` is one of the options specified below.
-There are a few reserved hash names:
-Any options of the form ``all.{option}`` will be inherited by all hashes
-if they do not have a ``{hash}.{option}`` value overriding the default.
-Any options of the form ``context.{option}`` will be treated as options for the context object itself,
-and not for a specified hash. Any options of the form ``{option}`` are taken to implicitly
-belong to the context, and are treated as if they started with the prefix ``context.``.
-The remaining options -
+ Example: ``schemes=["sha256_crypt", "md5_crypt", "des_crypt"]``.
-``context.schemes``
- comma separated list of the schemes this context should recognize, specified by name.
- when a context is identifying hashes, it will check each scheme in this list
- in order. if this value is being specified programmatically,
- it may also be a python list containing a mixture of names
- and password hash handler objects.
+``deprecated``
-``context.deprecated``
- comma separated list of the schemes which this context should recognize,
- generated hashes only if explicitly requested, and for which ``context.hash_needs_update()`` should return ``False``.
- if not specified, none are considered deprecated.
- this must be a subset of the names listed in context.schemes
+ List of handler names which should be considered deprecated by the CryptContext.
+ This should be a subset of the names of the handlers listed in schemes.
+ This is optional, if not specified, no handlers will be considered deprecated.
-``context.default``
- the default scheme context should use for generating new hashes.
- if not specified, the first entry in ``context.schemes`` is used.
+ For use in INI files, this may also be specified as a single comma-separated string
+ of handler names.
-``context.min_verify_time``
- if specified, all ``context.verify()`` calls will take at least this many seconds.
- if set to an amount larger than the time used by the strongest hash in the system,
- this prevents an attacker from guessing the strength of particular hashes remotely.
- (specified in fractional seconds).
+ This is primarily used by :meth:`CryptContext.hash_needs_update` and :meth:`CryptPolicy.handler_is_deprecated`.
+ If the application does not use these methods, this option can be ignored.
-``{hash}.min_rounds``, ``{hash}.max_rounds``
+ Example: ``deprecated=["des_crypt"]``.
- place limits on the number of rounds allowed for a specific hash.
+``default``
- * these are configurable per-context limits, hard limits set by algorithm are always applied
- * if min > max, max will be increased to equal min.
- * ``context.genconfig()`` or ``config.encrypt()`` - requests outside of these bounds will be clipped.
- * ``context.hash_needs_update()`` - existing hashes w/ rounds outside of range are not compliant
- * for hashes which do not have a rounds parameter, these values are ignored.
+ Specifies the name of the default handler to use when encrypting a new password.
+ If no default is specified, the first handler listed in ``schemes`` will be used.
-``{hash}.default_rounds``
+ Example: ``default="sha256_crypt"``.
- sets the default number of rounds to use when generating new hashes.
+``min_verify_time``
- * if this value is out side of per-policy min/max, it will be clipped just like user provided value.
- * ``context.genconfig()`` or ``config.encrypt()`` - if rounds are not provided explicitly, this value will be used.
- * for hashes which do not have a rounds parameter, this value is ignored.
- * if not specified, max_rounds is used if available, then min_rounds, then the algorithm default.
+ If specified, all :meth:`CryptContext.verify` calls will take at least this many seconds.
+ If set to an amount larger than the time used by the strongest hash in the system,
+ this prevents an attacker from guessing the strength of particular hashes through timing measurements.
-``{hash}.vary_rounds``
+ Specified in integer or fractional seconds.
- [only applies if ``{hash}.default_rounds`` is specified and > 0]
+ Example: ``min_verify_time=0.1``.
- if specified, every time a new hash is created using {hash}/default_rounds for it's rounds value,
- the actual value used is generated at random, using default_rounds as a hint.
+.. note::
- * integer value - a value will be chosen using the formula ``randint(default_rounds-vary_rounds, default_rounds+vary_rounds)``.
- * integer value between 0 and 100 with ``%`` suffix - same as above, with integer value equal to ``vary_rounds*default_rounds/100``.
- * note that if algorithms indicate they use a logarthmic rounds parameter, the percent syntax equation uses ``log(vary_rounds*(2**default_rounds)/100,2)``,
- to permit a default value to be applicable to all schemes. XXX: this might be a bad / overly complex idea.
+ For symmetry with the format of the hash option keywords (below),
+ all of the above context option keywords may also be specified
+ using the format :samp:`context__{option}` (note double underscores),
+ or :samp:`context.{option}` within INI files.
-``{hash}.{setting}``
- any keys which match the name of a configuration parameter accepted by the hash
- will be used directly as default values.
+.. note::
- * for security purposes, ``salt`` is *forbidden* from being used in this way.
- * if ``rounds`` is specified directly, it will override the entire min/max/default_rounds framework.
+ To override context options for a particular :ref:`user category <user-categories>`,
+ use the format :samp:`{category}__context__{option}`,
+ or :samp:`{category}.context.{option}` within an INI file.
-``{hash}.{other}``
- any keys which do not fall under the above categories will be ignored
+Hash Options
+============
+The following keyword options are accepted by both the :class:`CryptContext`
+and :class:`CryptPolicy` constructors, and affect how a :class:`!CryptContext` instance
+treats hashes belonging to a particular hash scheme, as identified by the hash's handler name.
-User Categories
-===============
-One frequent need is for certain categories of users (eg the root account)
-to have more strigent password requirements than default users.
-PassLib allows this by recognizing options of the format ``{category}.{name}.{option}``,
-and allowing many of it's entry methods to accept an optional ``category`` parameter.
+All hash option keywords should be specified using the format :samp:`{hash}__{option}`
+(note double underscores); where :samp:`{hash}` is the name of the hash's handler,
+and :samp:`{option}` is the name of the specific options being set.
+Within INI files, this may be specified using the alternate format :samp:`{hash}.{option}`.
+
+:samp:`{hash}__default_rounds`
+
+ Sets the default number of rounds to use when generating new hashes (via :meth:`CryptContext.encrypt`).
+
+ If not set, this will use max rounds hash option (see below),
+ or fall back to the algorithm-specified default.
+ For hashes which do not support a rounds parameter, this option is ignored.
+
+:samp:`{hash}__vary_rounds`
+
+ if specified along with :samp:`{hash}__default_rounds`,
+ this will cause each new hash created by :meth:`CryptContext.encrypt`
+ to have a rounds value random chosen from the range :samp:`{default_rounds} +/- {vary_rounds}`.
+
+ this may be specified as an integer value, or as a string containing an integer
+ with a percent suffix (eg: ``"10%"``). if specified as a percent,
+ the amount varied will be calculated as a percentage of the :samp:`{default_rounds}` value.
+
+ The default passlib policy sets this to ``"10%"``.
+
+ .. note::
+
+ If this is specified as a percentage, and the hash algorithm
+ uses a logarithmic rounds parameter, the amount varied
+ will be calculated based on the effective number of linear rounds,
+ not the actual rounds value.
+ This allows ``vary_rounds`` to be given a default value for all hashes
+ within a context, and behave sanely for both linear and logarithmic rounds parameters.
+
+:samp:`{hash}__min_rounds`, :samp:`{hash}__max_rounds`
+
+ Place limits on the number of rounds allowed for a specific hash.
+ ``min_rounds`` defaults to 0, ``max_rounds`` defaults to unlimited.
+
+ When encrypting new passwords with the specified hash (via :meth:`CryptContext.encrypt`),
+ the number of rounds will be clipped to these boundaries.
+ When checking for out-of-date hashes (via :meth:`CryptContext.hash_needs_update`),
+ it will flag any whose rounds are outside the range specified as needing to be re-encrypted.
+ For hashes which do not support a rounds parameter, these options are ignored.
-When one is specified, any ``{category}.{name}.{option}`` keywords in the configuration
-will override any ``{name}.{option}`` keywords.
+ .. note::
-In order to simplify behavior and implementation, categories cannot override the ``context/schemes`` keyword,
-though they may override the other context keys.
+ These are configurable per-context limits,
+ they will be clipped by any hard limits set in the hash algorithm itself.
-Default Policies
-================
-PassLib defines a library-default policy, updated perodically, providing (hopefully) sensible defaults for the various contexts.
+:samp:`{hash}__{setting}`
+
+ Any other option values, which match the name of a parameter listed
+ in the hash algorithm's ``handler.setting_kwds`` attribute,
+ will be passed directly to that hash whenever :meth:`CryptContext.encrypt` is called.
+
+ For security purposes, ``salt`` is *forbidden* from being used in this way.
+
+ If ``rounds`` is specified directly, it will override the entire min/max/default_rounds framework.
+
+.. note::
+
+ Default options which will be applied to all hashes within the context
+ can be specified using the special hash name ``all``. For example, ``all__vary_rounds="10%"``
+ would set the ``vary_rounds`` option to ``"10%"`` for all hashes, unless
+ it was overridden for a specific hash, such as by specifying ``sha256_crypt__vary_rounds="5%"``.
+ This feature is generally only useful for the ``vary_rounds`` hash option.
+
+.. _user-categories:
+
+User Categories
+===============
+CryptContext offers an optional feature of "user categories":
+
+User categories take the form of a string (eg: ``admin`` or ``guest``),
+passed to the CryptContext when one of it's methods is called.
+These may be set by an application to indicate the hash belongs
+to a user account which should be treated according to a slightly
+different set of configuration options from normal user accounts;
+this may involve requiring a stronger hash scheme, a larger
+number of rounds for that scheme, or just a longer verify time.
+
+If an application wishes to use this feature, it all that is needed
+is to prefix the name of any hash or context options with the name
+of the category string it wants to use, and add an additional separator to the keyword:
+:samp:`{category}__{hash}__{option}`` or ``{category}__context__{option}``.
+
+.. note::
+
+ For implementation & predictability purposes,
+ the context option ``schemes`` cannot be overridden per-category,
+ though all other options are allowed. In most cases,
+ the need to use a different hash for a particular category
+ can instead be acheived by overridden the ``default`` context option.
+
+Default Policy
+==============
+PassLib defines a library-default policy, providing (hopefully) sensible defaults for new contexts.
When a new CryptContext is created, a policy is generated from it's constructor arguments, which is then composited
over the library-default policy. You may optionally override the default policy used by overriding the ``policy`` keyword
-of CryptContext. This keyword accepts a single CryptPolicy object or string (which will be treated as an ini file to load);
-it also accepts a list of CryptPolicys and/or strings, which will be composited together along with any constructor options.
+of CryptContext. This default policy object may be imported as :data:`passlib.context.default_policy`,
+or viewed in the source code under ``$SOURCE/passlib/default.cfg``.
Sample Policy File
==================
@@ -138,7 +199,30 @@ A sample policy file::
sha512_crypt.min_rounds = 40000
bcrypt.min_rounds = 10
- #create a "root" category, which uses bcrypt by default, and has stronger hashes
- root.context.fallback = bcrypt
- root.sha512_crypt.min_rounds = 100000
- root.bcrypt.min_rounds = 13
+ #create a "admin" category, which uses bcrypt by default, and has stronger hashes
+ admin.context.fallback = bcrypt
+ admin.sha512_crypt.min_rounds = 100000
+ admin.bcrypt.min_rounds = 13
+
+And the equivalent as a set of python keyword options::
+
+ dict(
+ #configure what schemes the context supports (note the "context." prefix is implied for these keys)
+ schemes = ["md5_crypt", "sha512_crypt", "bcrypt" ],
+ deprecated = ["md5_crypt"],
+ default = "sha512_crypt",
+ min_verify_time = 0.1,
+
+ #set some common options for all schemes
+ all__vary_rounds = "10%",
+
+ #setup some hash-specific defaults
+ sha512_crypt__min_rounds = 40000,
+ bcrypt__min_rounds = 10,
+
+ #create a "admin" category, which uses bcrypt by default, and has stronger hashes
+ admin__context__fallback = bcrypt
+ admin__sha512_crypt__min_rounds = 100000
+ admin__bcrypt__min_rounds = 13
+ )
+
diff --git a/docs/lib/passlib.context.rst b/docs/lib/passlib.context.rst
index b3af128..13cbde8 100644
--- a/docs/lib/passlib.context.rst
+++ b/docs/lib/passlib.context.rst
@@ -13,7 +13,7 @@ Similarly, over time, applications may need to deprecate password schemes
in favor of newer ones, or raise the number of rounds required
by existing hashes.
-This module provides the :class:`!CryptContext` class, which is designed
+This module provides the :class:`CryptContext` class, which is designed
to handle (as much as possible) of these tasks for an application.
Essentially, a :class:`!CryptContext` instance contains a list
of hash handlers that it should recognize, along with information
@@ -21,17 +21,9 @@ about which ones are deprecated, which is the default,
and what configuration constraints an application has placed
on a particular hash.
-Since this class contains so many methods and options,
-the documentation for this module is broken up into three
-sections:
-
-* Usage examples (below)
-* Next, documentation of the complete :doc:`CryptContext interface <passlib.context-interface>`.
-* Finally, a comprehensive list of :doc:`CryptContext options <passlib.context-options>`.
-
Usage
=====
-To start off with a simple example::
+To start off with a simple example of how to create and use a CryptContext::
>>> from passlib.context import CryptContext
@@ -67,8 +59,8 @@ To start off with a simple example::
>>> myctx.identify(hash1, resolve=True)
<class 'passlib.handlers.md5_crypt.md5_crypt'>
-All of the configuration options for a :class:`!CryptContext` instance
-are stored in a :class:`CryptPolicy` instance accessible through
+If introspection of a :class:`!CryptContext` instance
+is needed, all configuration options are stored in a :class:`CryptPolicy` instance accessible through
their ``policy`` attribute::
>>> from passlib.context import CryptContext
@@ -81,3 +73,13 @@ their ``policy`` attribute::
>>> #get the default handler class :
>>> myctx.policy.get_handler()
<class 'passlib.handlers.md5_crypt.md5_crypt'>
+
+Interface
+=========
+This details the constructors and methods provided by :class:`!CryptContext`
+and :class:`!CryptPolicy`. A list of all the keyword options accepted by these classes is listed separately
+in :doc:`passlib.context-options`.
+
+.. autoclass:: CryptContext(schemes=None, policy=<default policy>, \*\*kwds)
+
+.. autoclass:: CryptPolicy(\*\*kwds)
diff --git a/passlib/context.py b/passlib/context.py
index 6c19fb0..37987be 100644
--- a/passlib/context.py
+++ b/passlib/context.py
@@ -91,17 +91,16 @@ def parse_policy_items(source):
class CryptPolicy(object):
"""stores configuration options for a CryptContext object.
- .. note::
- Instances of CryptPolicy should be treated as immutable.
-
- Policy objects can be constructed by the following methods:
+ .. method:: __init__(**options)
- .. method:: (constructor)
+ The CryptPolicy class constructor accepts a dictionary
+ of keywords, which can include all the options
+ listed in the :ref:`cryptcontext-options`.
- You can specify options directly to the constructor.
- This accepts dot-seperated keywords such as found in the config file format,
- but for programmatic convience, it also accepts keys with ``.`` replaced with ``__``,
- allowing options to be specified programmatically in python.
+ Constructors
+ ============
+ In addition to passing in keywords directly,
+ CryptPolicy objects can be constructed by the following methods:
.. automethod:: from_path
.. automethod:: from_string
@@ -109,6 +108,8 @@ class CryptPolicy(object):
.. automethod:: from_sources
.. automethod:: replace
+ Introspection
+ =============
.. automethod:: has_schemes
.. automethod:: schemes
.. automethod:: iter_handlers
@@ -117,10 +118,15 @@ class CryptPolicy(object):
.. automethod:: handler_is_deprecated
.. automethod:: get_min_verify_time
+ Exporting
+ =========
.. automethod:: iter_config
.. automethod:: to_dict
.. automethod:: to_file
.. automethod:: to_string
+
+ .. note::
+ Instances of CryptPolicy should be treated as immutable.
"""
#=========================================================
@@ -599,22 +605,47 @@ default_policy = CryptPolicy.from_string(resource_string("passlib", "default.cfg
class CryptContext(object):
"""Helper for encrypting passwords using different algorithms.
- :param policy: optionally override the default policy CryptContext starts with before options are added.
- :param kwds: ``schemes`` and all other keywords are passed to the CryptPolicy constructor.
+ :param policy:
+ optionally override the default policy CryptContext starts with before options are added.
+
+ If not specified, the new instance will inherit a set of default options (such as rounds, etc)
+ from the passlib default policy (importable as :data:`passlib.context.default_policy`).
+
+ If explicitly set to ``None``, the new instance will not inherit from the default policy,
+ and will contain only the configuration specified by any additional keywords.
+
+ Alternately, a custom CryptPolicy instance can be passed in,
+ which allows loading the policy from a configuration file,
+ combining multiple policies together, and other features.
+ :param kwds:
+
+ ``schemes`` and all other keywords are passed to the CryptPolicy constructor,
+ or to :meth:`CryptPolicy.replace`, if a policy has also been specified.
+
+ .. automethod:: replace
+
+ Configuration
+ =============
.. attribute:: policy
This exposes the :class:`CryptPolicy` instance
which contains the configuration used by this context object.
- .. automethod:: hash_needs_update
+ This attribute may be written to (replacing it with another CryptPolicy instance),
+ in order to reconfigure a CryptContext while an application is running.
+ However, this should only be done for context instances created by the application,
+ and NOT for context instances provided by PassLib.
+
+ Main Interface
+ ==============
.. automethod:: identify
.. automethod:: encrypt
.. automethod:: verify
- .. automethod:: genconfig
- .. automethod:: genhash
- .. automethod:: replace
+ Migration Helpers
+ =================
+ .. automethod:: hash_needs_update
"""
#===================================================================
#instance attrs
diff --git a/passlib/registry.py b/passlib/registry.py
index cb380bd..6544f0c 100644
--- a/passlib/registry.py
+++ b/passlib/registry.py
@@ -108,6 +108,9 @@ _handler_locations = {
#: master regexp for detecting valid handler names
_name_re = re.compile("^[a-z][_a-z0-9]{2,}$")
+#: names which aren't allowed for various reasons (mainly keyword conflicts in CryptContext)
+_forbidden_names = frozenset(["policy", "context", "all", "default", "none"])
+
#==========================================================
#registry frontend functions
#==========================================================
@@ -175,6 +178,10 @@ def register_crypt_handler(handler, force=False, name=None):
raise ValueError, "name must be lower-case: %r" % (name,)
if not _name_re.match(name):
raise ValueError, "invalid characters in name (must be 3+ characters, begin with a-z, and contain only underscore, a-z, 0-9): %r" % (name,)
+ if '__' in name:
+ raise ValueError, "name may not contain double-underscores: %r" % (name,)
+ if name in _forbidden_names:
+ raise ValueError, "that name is not allowed: %r" % (name,)
#check for existing handler
other = _handlers.get(name)
diff --git a/setup.cfg b/setup.cfg
index 9adde5d..850f440 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,3 +1,3 @@
[egg_info]
-tag_build = a1
+tag_build = b1
diff --git a/setup.py b/setup.py
index 313abb2..d50a37e 100644
--- a/setup.py
+++ b/setup.py
@@ -29,11 +29,11 @@ setup(
description = "password hash library",
long_description = """\
-PassLib provides cross-platform implementations of most of the major
-password hashing algorithms; as well as a framework for managing
+PassLib is a password hash library, which provides cross-platform
+implementations of over 20 password hashing algorithms; as well as a framework for managing
and migrating existing password hashes. It's designed to be useful
-for anything from quickly verify a hash found in /etc/shadow,
-to integrating full-strength password hashing for multi-user application.
+for any task from quickly verifying a hash found in /etc/shadow,
+to providing full-strength password hashing for multi-user application.
""",
keywords = "password secret hash security crypt md5-crypt sha256-crypt sha512-crypt bcrypt htpasswd htdigest",