summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Collins <elic@assurancetechnologies.com>2016-11-20 14:11:35 -0500
committerEli Collins <elic@assurancetechnologies.com>2016-11-20 14:11:35 -0500
commita54c5ba533592f7113fd3a4a86bf8a036baa7860 (patch)
tree1c36f1329efb86a637ff365c3e7a6a8819ed3cc5
parentb214f86b7523f3adaf8bdcf78ffbddf351c0fb3d (diff)
downloadpasslib-a54c5ba533592f7113fd3a4a86bf8a036baa7860.tar.gz
docs: LARGE update to documentation, tutorials added, pages relocated
* moved a bunch of pages into 'docs/narr' narrative subsection. added placeholder pages in old locations, to minimize inbound link breakage. * split history into separate pages, was getting way too long. removed toplevel CHANGES file, not feasible under new structure. * passlib.ifc split into reference & tutorial portions, tutorial allowed subsuming a bunch of other hash-usage examples. * added standard fragments for warning about insecure hashes, added them to top of a LOT of hash doc pages. * updated references, various layout tweaks
-rw-r--r--CHANGES1033
-rw-r--r--LICENSE7
-rw-r--r--README2
-rw-r--r--docs/_fragments/insecure_hash_warning.rst9
-rw-r--r--docs/_fragments/trivial_hash_warning.rst8
-rw-r--r--docs/contents.rst4
-rw-r--r--docs/history.rst1
-rw-r--r--docs/history/1.5.rst173
-rw-r--r--docs/history/1.6.rst400
-rw-r--r--docs/history/1.7.rst305
-rw-r--r--docs/history/ancient.rst126
-rw-r--r--docs/history/index.rst22
-rw-r--r--docs/index.rst8
-rw-r--r--docs/install.rst12
-rw-r--r--docs/lib/index.rst55
-rw-r--r--docs/lib/passlib.apps.rst4
-rw-r--r--docs/lib/passlib.context.rst2
-rw-r--r--docs/lib/passlib.crypto.digest.rst4
-rw-r--r--docs/lib/passlib.exc.rst2
-rw-r--r--docs/lib/passlib.ext.django.rst2
-rw-r--r--docs/lib/passlib.hash.apr_md5_crypt.rst5
-rw-r--r--docs/lib/passlib.hash.bigcrypt.rst4
-rw-r--r--docs/lib/passlib.hash.bsdi_crypt.rst6
-rw-r--r--docs/lib/passlib.hash.cisco_asa.rst8
-rw-r--r--docs/lib/passlib.hash.cisco_pix.rst7
-rw-r--r--docs/lib/passlib.hash.cisco_type7.rst6
-rw-r--r--docs/lib/passlib.hash.crypt16.rst4
-rw-r--r--docs/lib/passlib.hash.des_crypt.rst5
-rw-r--r--docs/lib/passlib.hash.hex_digests.rst2
-rw-r--r--docs/lib/passlib.hash.lmhash.rst18
-rw-r--r--docs/lib/passlib.hash.md5_crypt.rst10
-rw-r--r--docs/lib/passlib.hash.msdcc.rst7
-rw-r--r--docs/lib/passlib.hash.mssql2000.rst7
-rw-r--r--docs/lib/passlib.hash.mssql2005.rst7
-rw-r--r--docs/lib/passlib.hash.mysql323.rst8
-rw-r--r--docs/lib/passlib.hash.mysql41.rst8
-rw-r--r--docs/lib/passlib.hash.nthash.rst9
-rw-r--r--docs/lib/passlib.hash.oracle10.rst7
-rw-r--r--docs/lib/passlib.hash.postgres_md5.rst5
-rw-r--r--docs/lib/passlib.hash.rst59
-rw-r--r--docs/lib/passlib.hash.scrypt.rst6
-rw-r--r--docs/lib/passlib.hosts.rst2
-rw-r--r--docs/lib/passlib.ifc.rst (renamed from docs/password_hash_api.rst)362
-rw-r--r--docs/narr/context-tutorial.rst (renamed from docs/lib/passlib.context-tutorial.rst)45
-rw-r--r--docs/narr/hash-tutorial.rst310
-rw-r--r--docs/narr/index.rst (renamed from docs/narrative.rst)9
-rw-r--r--docs/narr/overview.rst92
-rw-r--r--docs/narr/quickstart.rst (renamed from docs/new_app_quickstart.rst)181
-rw-r--r--docs/narr/totp-tutorial.rst (renamed from docs/lib/passlib.totp-tutorial.rst)6
-rw-r--r--docs/other.rst3
-rw-r--r--docs/overview.rst81
-rw-r--r--docs/reference.rst40
-rw-r--r--passlib/crypto/digest.py16
-rw-r--r--passlib/handlers/bcrypt.py2
-rw-r--r--passlib/pwd.py8
-rw-r--r--passlib/registry.py4
-rw-r--r--setup.py2
57 files changed, 1867 insertions, 1673 deletions
diff --git a/CHANGES b/CHANGES
deleted file mode 100644
index 87a38a6..0000000
--- a/CHANGES
+++ /dev/null
@@ -1,1033 +0,0 @@
-.. -*- restructuredtext -*-
-
-.. _whats-new:
-
-===============
-Release History
-===============
-
-Upcoming Changes
-================
-
-As a heads-up, developers may be impacted by the following changes
-planned for future releases:
-
-* **v1.8:**
-
- - :mod:`passlib.context`: Removal of long-deprecated :class:`!CryptPolicy` class.
- - :mod:`passlib.apache`: Removal of deprecated v1.5 compatibility methods.
-
-* **v2.0:**
-
- .. currentmodule:: passlib.ifc
-
- - A *large* number of deprecated methods and features will be removed;
- primarily the deprecated :meth:`PasswordHash.encrypt`
- and :meth:`CryptContext.encrypt` aliases.
-
- - :mod:`passlib.context`: :class:`!CryptContext` objects will default to ``deprecated="auto"``,
- meaning all but the first scheme will be considered deprecated unless
- explicitly stated otherwise.
-
- - :class:`passlib.apache.HtpasswdFile` will default ``"bcrypt"``,
- generally requiring Apache 2.4. Forward & backward ``default_scheme``
- settings are available as of Passlib 1.7.
-
-.. rst-class:: emphasize-children toc-always-open
-
-**1.7** (NOT YET RELEASED)
-==========================
-
-.. todo::
-
- The following tasks are blocking the 1.7 release:
-
- * Finish the :mod:`passlib.totp` module (:issue:`44`)
-
- - tests
- - narrative documentation
- - audit encrypted mode code
-
- * :mod:`passlib.pwd`
-
- - final length should be adjusted to account for sequence space
- that's omitted by min_complexity cutoff; or decide this is non-issue.
-
- - decide if this is ready, or if should be pushed to 1.8 --
- should remove announcement from 1.7 changelog in that case.
-
- * Get :mod:`passlib.apache` context profiles finished & committed.
-
-Overview
---------
-
- *Welcome to Passlib 1.7!*
-
- This release includes a number of new features, cleans up
- some long-standing design issues, and contains a number of internal
- improvements; all part of the roadmap towards a leaner and simpler Passlib 2.0.
-
- *Highlights include:*
-
- * Support for :class:`~passlib.hash.argon2` and
- :class:`~passlib.hash.scrypt` hashes.
-
- .. currentmodule:: passlib.ifc
-
- * The misnamed :meth:`PasswordHash.encrypt` method is deprecated, new code should
- now call :meth:`PasswordHash.hash` instead. This is part of a much
- larger project to clean up passlib's password hashing API
- (see *Deprecations* below)
-
- * Experimental TOTP (two factor authentication) helpers in the :mod:`passlib.totp` module.
-
- * Large speedup of the internal PBKDF2 routines.
-
-Requirements
-------------
-
- * **Passlib now requires Python 2.6, 2.7, or >= 3.3**.
- Support for Python versions 2.5 and 3.0 through 3.2 have been dropped.
- Support for PyPy 1.x has also been dropped.
-
- * The :mod:`passlib.ext.django` extension now requires Django 1.8 or better.
- Django 1.7 and earlier are no longer supported.
-
-New Features
-------------
-
-*New Hashes*
-
- * :doc:`passlib.hash.argon2 </lib/passlib.hash.argon2>` --
- Support for the Argon2 password hash (:issue:`69`).
-
- * :doc:`passlib.hash.scrypt </lib/passlib.hash.scrypt>` --
- New password hash format which uses the SCrypt KDF (:issue:`8`).
-
- * :doc:`passlib.hash.cisco_asa </lib/passlib.hash.cisco_asa>` --
- Support for Cisco ASA 7.0 and newer hashes (:issue:`51`).
- *Note: this should be considered experimental, and needs verification
- of it's test vectors.*
-
-*New Modules*
-
- * New :mod:`passlib.totp` module provides full support for TOTP tokens
- on both client and server side. This module contains both low-level primitives,
- and high-level helpers for persisting and tracking client state.
-
- * New :mod:`passlib.pwd` module added to aid in password generation.
- Features support for alphanumeric passwords, or generation
- of phrases using wordsets such as Diceware.
-
-*CryptContext Features*
-
- * The :class:`~passlib.context.CryptContext` object now has helper
- methods for dealing with hashes representing
- :ref:`disabled accounts <context-disabled-hashes>` (:issue:`45`).
-
- * The :class:`~passlib.context.CryptContext` object now supports
- a :ref:`harden_verify <context-harden-verify-option>` option,
- allowing applications to introduce a delay in verification
- to help prevent attackers discovering weak or missing hashes
- through timing attacks.
-
- * All hashers which truncate passwords (e.g. :class:`~passlib.hash.bcrypt`
- and :class:`~passlib.hash.des_crypt`) can now be configured to raise
- a :exc:`~passlib.exc.PasswordTruncateError` when a overly-large password is provided.
- This configurable via (for example) ``bcrypt.using(truncate_error=True).hash(secret)``,
- or globally as an option to CryptContext (:issue:`59`).
-
-*Cryptographic Backends*
-
- * The :func:`~passlib.crypto.digest.pbkdf2_hmac` function and all PBKDF2-based
- hashes have been sped up by ~20% compared to Passlib 1.6. For an even greater
- speedup, it will now take advantage of the external `fastpbk2 <https://pypi.python.org/pypi/fastpbkdf2>`_
- library, or stdlib's :func:`hashlib.pbkdf2_hmac` (when available).
-
-Bugfixes
---------
- * :class:`~passlib.hash.bcrypt`: Passlib will now detect and work around
- a fatal concurrency bug in py-bcrypt 0.2 and earlier
- (a :exc:`~passlib.exc.PasslibSecurityWarning` will also be issued).
- Nevertheless, users are *strongly* encouraged to upgrade to py-bcrypt 0.3
- or another bcrypt library if you are using the
- :doc:`bcrypt </lib/passlib.hash.bcrypt>` hash.
-
- * :class:`~passlib.CryptContext` instances now pass contextual keywords (such as `"user"`)
- to the hashes that support them, but ignore them for hashes that don't (:issue:`63`).
-
- * The :mod:`passlib.apache` htpasswd helpers now preserve blank lines and comments,
- rather than throwing a parse error (:issue:`73`).
-
- * :mod:`passlib.ext.django` and unittests: compatibility fixes for Django 1.9,
- and some internal cleanups (:issue:`68`).
-
- * The :class:`~passlib.hash.django_disabled` hash now appends
- a 40-char alphanumeric string, to match Django's behavior.
-
-Other Changes
--------------
-
-* :class:`~passlib.hash.bcrypt` and :class:`~passlib.hash.bcrypt_sha256`
- now default to the "2b" format.
-
-* :class:`passlib.apache.HtpasswdFile` updated to match Apache 2.4's
- hash schemes, as well as all host OS crypt formats; allowing for much more
- secure hashes in htpasswd files. You can now specify if the default hash
- should be compatible with apache 2.2 / 2.4, and host-specific or portable.
- See the ``default_schemes`` keyword for details.
-
-*Internal Changes*
-
- .. currentmodule:: passlib.ifc
-
- * The majority of CryptContext's internal rounds handling & migration code has been
- moved to the password hashes themselves, taking advantage of the new :meth:`PasswordHash.using`
- and :meth:`PasswordHash.needs_update` methods.
-
- This allows much more flexibility when configuring a hasher directly,
- as well making it easier for CryptContext to support hash-specific parameters.
-
- * The shared :class:`!PasswordHash` unittests now check all hash handlers for
- basic thread-safety (motivated by the pybcrypt 0.2 concurrency bug).
-
- * :func:`~passlib.utils.consteq` is now wraps stdlib's :func:`hmac.compare_digest`
- when available (python 2.7.11, python 3.3 and up).
-
-.. _encrypt-method-cleanup:
-
-Deprecations
-------------
-As part of a long-range plan to restructure and simplify both the API and the internals of Passlib,
-a number of methods have been deprecated & replaced. The eventually goal is a large cleanup
-and overhaul as part of Passlib 2.0. There will be at least one more 1.x version
-before Passlib 2.0, to provide a final transitional release.
-
-Password Hash API Deprecations
-..............................
- .. currentmodule:: passlib.ifc
-
- As part of this cleanup, the :class:`~passlib.ifc.PasswordHash` API (used by all hashes in passlib),
- has had a number of changes:
-
- * **[major]** The :meth:`!PasswordHash.encrypt` method
- has been renamed to :meth:`PasswordHash.hash`,
- to clarify that it's performing one-way hashing rather than reversiable encryption.
- A compatibility alias will remain in place until Passlib 2.0.
- This should fix the longstanding :issue:`21`.
-
- * **[major]** Passing explicit configuration options to the :meth:`!PasswordHash.encrypt` method
- (now called :meth:`PasswordHash.hash`) is deprecated.
- To provide settings such as ``rounds`` and ``salt_size``, callers
- should use the new :meth:`PasswordHash.using`
- method, which generates a new hasher with a customized configuration.
-
- >>> # for example, instead of this:
- >>> sha256_crypt.encrypt("secret", rounds=12345)
-
- >>> # callers should now use:
- >>> sha256_crypt.using(rounds=12345).hash("secret")
-
- Support for the old syntax will be removed in Passlib 2.0.
-
- .. note::
-
- This doesn't apply to contextual options such as :class:`~passlib.hash.cisco_pix`'s
- ``user`` keyword, which should still be passed into the :meth:`!hash` method.
-
- * **[minor]** The little-used :meth:`PasswordHash.genhash` and
- :meth:`PasswordHash.genconfig` methods have been deprecated.
- Compatibility aliases will remain in place until Passlib 2.0,
- at which point they will be removed entirely.
-
-Crypt Context API Deprecations
-..............................
- .. currentmodule:: passlib.context
-
- Applications which use passlib's :class:`~passlib.context.CryptContext` should not be
- greatly affected by this release; only one major deprecation was made:
-
- * **[major]** To match the :class:`!PasswordHash` API changes above,
- the :meth:`!CryptContext.encrypt` method was renamed to :meth:`CryptContext.hash`.
- A compatibility alias will remain until Passlib 2.0.
-
- A fewer internal options and infrequently used features have been deprecated:
-
- * **[minor]** :meth:`CryptContext.hash`, :meth:`~CryptContext.verify`,
- :meth:`~CryptContext.verify_and_update`, and
- :meth:`~CryptContext.needs_update`:
- The ``scheme`` keyword is now deprecated; support will be removed in Passlib 2.0.
-
- * **[minor]** :meth:`CryptContext.hash`: Passing
- settings keywords to :meth:`!hash` such as ``rounds`` and ``salt`` is deprecated.
- Code should now get ahold of the default hasher, and invoke it explicitly::
-
- >>> # for example, calls that did this:
- >>> context.hash(secret, rounds=1234)
-
- >>> # should use this instead:
- >>> context.handler().using(rounds=1234).hash(secret)
-
- * **[minor]** The ``vary_rounds`` option has been deprecated,
- and will be removed in Passlib 2.0. It provided very little security benefit,
- and was judged not worth the additional code complexity it requires.
-
- * **[minor]** The special wildcard ``all`` scheme name
- has been deprecated, and will be removed in Passlib 2.0. The only legitimate use
- was to support ``vary_rounds``, which itself will be removed in 2.0.
-
-Other Deprecations
-..................
- A few other assorted deprecations have been made:
-
- * The :func:`~passlib.utils.generate_secret` function has been deprecated
- in favor of the new :mod:`passlib.pwd` module, and the old function will be removed
- in Passlib 2.0.
-
- * Most of passlib's internal cryptography helpers have been moved from
- :mod:`passlib.utils` to :mod:`passlib.crypto`, and the APIs refactored.
- This allowed unification of various hash management routines,
- some speed ups to the HMAC and PBKDF2 primitives, and opens up the architecture
- to support more optional backend libraries.
-
- Compatibility wrappers will be kept in place at the old location until Passlib 2.0.
-
- * Some deprecations and internal changes have been made to the :mod:`passlib.utils.handlers`
- module, which provides the common framework Passlib uses to implement hashers.
-
- .. warning::
-
- Developers who are importing from the :mod:`!passlib.utils.handlers` module directly are strongly encouraged
- to contact the Passlib message board. Backwards-incompatible relocations will occur in the
- Passlib 1.8 / 1.9 releases.
-
-Backwards Incompatibilities
----------------------------
-Changes in existing behavior:
-
- * **[moderate]** :mod:`passlib.apache`: New hashes generated by :class:`~passlib.apache.HtpasswdFile` now use the strongest
- algorithm available on the host, rather than one that is guaranteed to be portable.
- Applications can explicitly set ``HtPasswdFile(default_scheme="portable")`` to restore the old behavior.
-
- * **[minor]** M2Crypto no longer used to accelerate pbkdf2-hmac-sha1; applications relying on this
- to speed up :class:`~passlib.hash.pbkdf2_sha1` should install
- `fastpbkdf2 <https://pypi.python.org/pypi/fastpbkdf2>`_.
-
-Scheduled removal of features:
-
- * **[minor]** :mod:`passlib.context`: The :ref:`min_verify_time <context-min-verify-time-option>` keyword
- that was deprecated in release 1.6, is now completely ignored.
- Support will be removed entirely in release 1.8.
- See the new :ref:`harden_verify <context-harden-verify-option>` keyword
- that replaces it.
-
- * **[trivial]** :mod:`passlib.hash`: The internal :meth:`!PasswordHash.parse_rounds` method, deprecated in 1.6, has been removed.
-
-Minor incompatibilities:
-
- * **[minor]** :mod:`passlib.hash`: The little-used method :meth:`~passlib.ifc.PasswordHash.genconfig`
- will now always return a valid hash, rather than a truncated configuration
- string or ``None``.
-
- * **[minor]** :mod:`passlib.hash`: The little-used method :meth:`~passlib.ifc.PasswordHash.genhash` no longer accepts
- ``None`` as a config argument.
-
- * **[trivial]** :func:`passlib.utils.pbkdf2.pbkdf2` no longer supports custom PRF callables.
- this was an unused feature, and prevented some useful optimizations.
-
------
-
-.. centered::
- **END OF 1.7 RELEASE NOTES**
-
------
-
-**1.6.5** (2015-08-04)
-======================
-
- Fixed some minor bugs in the test suite which were causing erroneous test failures
- (:issue:`57` and :issue:`58`). The passlib library itself is unchanged.
-
-.. rst-class:: toc-always-toggle
-
-**1.6.4** (2015-07-25)
-======================
-
- This release rolls up assorted bug & compatibility fixes since 1.6.2.
-
-Bugfixes
---------
-
- * Correctly detect bcrypt 2.0. Previous releases were incorrectly detecting it as py-bcrypt,
- causing spurious errors (:issue:`56`).
-
- * CryptContext now accepts scheme names as unicode (:issue:`54`).
-
- * :mod:`passlib.ext.django` now works correctly with Django 1.7-1.8. Previous
- releases had various test failures (:issue:`52`).
-
- * :class:`passlib.apache.HtpasswdFile` now recognizes bcrypt, sha256_crypt, sha512_crypt
- hashes (:issue:`55`).
-
-BCrypt Changes
---------------
-
- A few changes have been made to the :class:`~passlib.hash.bcrypt` hash:
-
- * It now supports the ``$2b$`` hash format.
-
- * It will now issue a :exc:`~passlib.exc.PasslibSecurityWarning` if the active backend
- is vulnerable to the :ref:`wraparound bug <bsd-wraparound-bug>`,
- and automatically enable a workaround (py-bcrypt is known to be vulnerable as of v0.4).
-
- * It will throw a :exc:`~passlib.exc.PasslibSecurityError` if the active backend
- is vulnerable to the :ref:`8-bit bug <crypt-blowfish-bug>` (none of Passlib's
- backends are known to be vulnerable as of 2015-07).
-
- * Updated documentation to indicate the cffi-based `bcrypt <https://pypi.python.org/pypi/bcrypt>`_
- library is now the recommended bcrypt backend.
-
- * Backend capability detection code refactored to rely on runtime detection
- rather than hardcoded information.
-
-Other Changes
--------------
-
- * Source repo's ``tox.ini`` updated. Now assumes python3 by default, and refactored test
- environments to more cleanly delineate the different setups being tested.
-
- * Passlib releases are now published as wheels instead of eggs.
-
-**1.6.3** (2015-07-25)
-======================
-
- This was relabeled as **1.6.4** due to PyPI upload issues.
-
-**1.6.2** (2013-12-26)
-======================
-
- Minor changes & compatibility fixes
-
- * Re-tuned the :attr:`~passlib.ifc.PasswordHash.default_rounds` values for all of the hashes.
-
- * Added the new :doc:`bcrypt_sha256 <lib/passlib.hash.bcrypt_sha256>` hash,
- which wraps BCrypt using SHA256 in order to work around BCrypt's password size limitations
- (:issue:`43`).
-
- * :doc:`passlib.hash.bcrypt <lib/passlib.hash.bcrypt>`:
- Added support for the `bcrypt <https://pypi.python.org/pypi/bcrypt>`_
- library as one of the possible bcrypt backends that will be used if available.
- (:issue:`49`)
-
- * :mod:`passlib.ext.django`: Passlib's Django extension
- (and it's related hashes and unittests) have been updated to handle
- some minor API changes in Django 1.5-1.6. They should now be compatible with Django 1.2 and up.
- (:issue:`50`)
-
-**1.6.1** (2012-08-02)
-======================
-
- Minor bugfix release
-
- * *bugfix*: Various :class:`~passlib.context.CryptContext` methods
- would incorrectly raise :exc:`TypeError` if passed a :class:`!unicode`
- user category under Python 2. For consistency,
- :class:`!unicode` user category values are now encoded to ``utf-8`` :class:`bytes` under Python 2.
-
- * *bugfix*: Reworked internals of the :class:`CryptContext` config compiler
- to fix a couple of border cases (:issue:`39`):
-
- - It will now throw a :exc:`ValueError`
- if the :ref:`default <context-default-option>` scheme is marked as
- :ref:`deprecated <context-deprecated-option>`.
- - If no default scheme is specified, it will use the first
- *non-deprecated* scheme.
- - Finally, it will now throw a :exc:`ValueError` if all schemes
- are marked as deprecated.
-
- * *bugfix*: FreeBSD 8.3 added native support for :class:`~passlib.hash.sha256_crypt` --
- updated Passlib's unittests and documentation accordingly (:issue:`35`).
-
- * *bugfix:* Fixed bug which caused some :mod:`!passlib.apache` unittests to fail
- if mtime resolution >= 1 second (:issue:`35`).
-
- * *bugfix:* Fixed minor bug in :mod:`!passlib.registry`, should now work correctly under Python 3.3.
-
- * Various documentation updates and corrections.
-
-**1.6** (2012-05-01)
-====================
-
-Overview
---------
-
- Welcome to Passlib 1.6.
-
- The main goal of this release was to clean up the codebase, tighten input
- validation, and simplify the publically exposed interfaces. This release also
- brings a number of other improvements: 10 or so new hash algorithms,
- additional security precautions for the existing algorithms,
- a number of speed improvements, and updated documentation.
-
-Deprecated APIs
-...............
- In order to improve the publically exposed interface,
- some of the more cumbersome and less-used functions in Passlib
- have been deprecated / renamed. This should not affect 99% of applications.
- That said, all the deprecated interfaces are still present, and will continue
- to be supported for at least one more major release.
- To help with migration, all deprecated functions should issue an informative
- :exc:`DeprecationWarning` when they are invoked, detailing their suggested replacement.
- The following interfaces have changed:
-
- * The semi-internal :class:`!CryptPolicy` class has been deprecated
- in its entirety. All functionality has been rolled into the
- parent :class:`!CryptContext` class (see :ref:`below <crypt-policy-deprecated>` for more).
-
- * The interface of the :mod:`passlib.apache` classes has been improved:
- some confusing methods and options have been renamed, some new
- constructors and other functions have been added.
-
- * The (undocumented) :mod:`!passlib.win32` module has been deprecated,
- all of its functionality is now offered through the
- :doc:`lmhash <lib/passlib.hash.lmhash>` and :doc:`nthash <lib/passlib.hash.nthash>`
- algorithms.
-
-New Hashes
-----------
- The release adds support for a number of hash algorithms:
-
- :doc:`cisco_pix <lib/passlib.hash.cisco_pix>`, :doc:`cisco_type7 <lib/passlib.hash.cisco_type7>`
- Two hash formats frequently found on various
- Cisco devices *(for Cisco Type 5 hashes, see*
- :doc:`md5_crypt <lib/passlib.hash.md5_crypt>` *).*
-
- :ref:`django_pbkdf2_sha256 <django-1.4-hashes>`, :ref:`django_pbkdf2_sha1 <django-1.4-hashes>`, :ref:`django_bcrypt <django-1.4-hashes>`
- All three of the new hash schemes introduced in Django 1.4.
-
- :doc:`lmhash <lib/passlib.hash.lmhash>`, :doc:`nthash <lib/passlib.hash.nthash>`
- Microsoft's legacy "Lan Manager" hash, and the replacement
- NT password hash. *(the old* ``nthash`` *algorithm in Passlib 1.5 has been renamed to*
- :class:`~passlib.hash.bsd_nthash` *, to reflect its lineage)*.
-
- :doc:`msdcc <lib/passlib.hash.msdcc>`, :doc:`msdcc2 <lib/passlib.hash.msdcc2>`
- Microsoft Windows' Domain Cached Credentials, versions 1 and 2.
- These algorithms also go by the names "DCC", "MSCache", and "MSCash".
-
- :doc:`mssql2000 <lib/passlib.hash.mssql2000>`, :doc:`mssql2005 <lib/passlib.hash.mssql2005>`
- Hash algorithms used by MS SQL Server 2000 and later.
-
- :doc:`scram <lib/passlib.hash.scram>`
- A hash format added specifically for storing the complex digest
- information needed to authenticate a user via the SCRAM protocol
- (:rfc:`5802`). It can also be used in the same way as any other
- password hash in Passlib.
-
-Existing Hashes
----------------
- Additionally, the following new features have been added to the existing hashes:
-
- .. _password-size-limit:
-
- *Password Size Limit*
- All hashes in Passlib will now throw :exc:`~passlib.exc.PasswordSizeError`
- if handed a password that's larger than 4096 characters.
-
- This limit should be larger than any reasonable password size,
- and prevents various things including DOS abuses, and exploitation
- of OSes with a buggy :func:`!crypt` implementation.
- See :exc:`~passlib.exc.PasswordSizeError` for how to change this limit.
-
- .. _consteq-issue:
-
- *Constant Time Comparison*
- All hash comparisons in Passlib now use the "constant time" [#consteq]_
- comparison function :func:`~passlib.utils.consteq`, instead
- of ``==``.
-
- This change is motivated a well-known `hmac timing attack <http://rdist.root.org/2009/05/28/timing-attack-in-google-keyczar-library/>`_
- which exploits short-circuit string comparisons.
- While this attack is not currently feasible against
- most password hashes, some of the weaker unsalted
- hashes supported by Passlib may be vulnerable; and this
- change has been made preventatively to all of them.
-
- .. [#consteq] "constant time" is a misnomer, it actually takes ``THETA(len(righthand_value))`` time.
-
- .. _strict-parameters:
-
- *Strict Parameters*
- Previous releases of Passlib would silently correct any invalid values
- (such as ``rounds`` parameters that were out of range). This is was deemed
- undesirable, as it leaves developers unaware they are requesting
- an incorrect (and potentially insecure) value.
-
- Starting with this release, providing invalid values to
- :meth:`PasswordHash.encrypt <passlib.ifc.PasswordHash.encrypt>`
- will result in a :exc:`ValueError`. However, most hashes now accept
- an optional ``relaxed=True`` keyword, which causes Passlib
- to try and correct invalid values, and if successful,
- issue a :exc:`~passlib.exc.PasslibHashWarning` instead.
- These warnings can then be filtered if desired.
-
- :doc:`bcrypt <lib/passlib.hash.bcrypt>`
- The BCrypt hash now supports the `crypt_blowfish <http://www.openwall.com/crypt/>`_ project's
- ``$2y$`` hash prefix.
-
- On an unrelated note, Passlib now offers an (experimental) pure-python
- implementation of BCrypt. Unfortunately, it's still *WAY* too slow to be
- suitable for production use; and is disabled by default.
- If you really need it, see the BCrypt :ref:`documentation <bcrypt-backends>`
- for how to enable it.
-
- :doc:`bsdi_crypt <lib/passlib.hash.bsdi_crypt>`
- BSDi-Crypt will now issue a :exc:`~passlib.exc.PasslibSecurityWarning`
- if an application requests an even number of rounds, due to
- a known weakness in DES. Existing hashes with an even number of rounds will
- now be flagged by :meth:`CryptContext.needs_update() <passlib.context.CryptContext.needs_update>`.
-
- :doc:`ldap_salted_{digest} </lib/passlib.hash.ldap_std>`
- The LDAP salted digests now support salts of any size
- from 4-16 bytes, though they still default to 4 (:issue:`30`).
-
- :doc:`md5_crypt </lib/passlib.hash.md5_crypt>`, :doc:`sha256_crypt </lib/passlib.hash.md5_crypt>`, :doc:`sha512_crypt </lib/passlib.hash.md5_crypt>`
- The builtin implementation of these hashes has been
- sped up by about 25%, using an additional pre-computation step.
-
- :doc:`unix_disabled <lib/passlib.hash.unix_disabled>`
- The :class:`!unix_fallback` handler has been deprecated,
- and will be removed in Passlib 1.8.
- Applications should use the stricter-but-equivalent
- :class:`!unix_disabled` handler instead.
-
- This most likely only affects internal Passlib code.
-
-.. _crypt-policy-deprecated:
-
-CryptContext
-------------
-
- .. currentmodule:: passlib.context
-
- The :ref:`CryptContext <context-overview>` class has had a thorough
- internal overhaul. While the primary interface has not changed
- at all, the internals are much stricter about input validation,
- common methods have shorter code-paths, and the
- construction and introspection of :class:`!CryptContext` objects
- has been greatly simplified.
- Changes include:
-
- * All new (and hopefully clearer) :ref:`tutorial <context-tutorial>`
- and :ref:`reference <context-reference>` documentation.
-
- * The :class:`CryptPolicy` class and the :attr:`!CryptContext.policy` attribute have been deprecated.
-
- This was a semi-internal class, which most applications
- were not involved with at all, but to be conservative about
- breaking things, the existing CryptPolicy interface
- will remain in-place and supported until Passlib 1.8.
-
- All of the functionality of this class has been rolled into
- :class:`!CryptContext` itself, so there's one less class to remember.
- Many of the methods provided by :class:`!CryptPolicy` are now
- :class:`!CryptContext` methods, most with the same name and call syntax.
- Information on migrating existing code can be found in
- the deprecation warnings issued by the class itself,
- and in the :class:`CryptPolicy` documentation.
-
- * Two new class constructors have been added (:meth:`CryptContext.from_path`
- and :meth:`CryptContext.from_string`) to aid in loading CryptContext objects
- directly from a configuration file.
-
- * The :ref:`deprecated <context-deprecated-option>` keyword
- can now be set to the special string ``"auto"``; which will
- automatically deprecate all schemes except for the default one.
-
- * The :ref:`min_verify_time <context-min-verify-time-option>` keyword
- has been deprecated, will be ignored in release 1.7, and will be removed in release 1.8.
- It was never very useful, and now complicates the internal code needlessly.
-
- * All string parsing now uses stdlib's :class:`!SafeConfigParser`.
-
- Previous releases used the original :class:`!ConfigParser` interpolation;
- which was deprecated in Passlib 1.5, and has now been removed.
- This should only affect strings which contained raw ``%`` characters,
- they will now need to be escaped via ``%%``.
-
-Other Modules
--------------
-
- * The api for the :mod:`passlib.apache` module has been updated
- to add more flexibility, and to fix some ambiguous method
- and keyword names. The old interface is still supported, but deprecated,
- and will be removed in Passlib 1.8.
-
- * Added the :data:`~passlib.apps.django14_context` preset to the
- the :mod:`!passlib.apps` module. this preconfigured CryptContext
- object should support all the hashes found in a typical Django 1.4
- deployment.
-
- * **new**: Added :mod:`passlib.ext.django`, a Django plugin which can be used to
- override Django's password hashing framework with a custom Passlib
- policy (an undocumented beta version of this was present in the 1.5 release).
-
- * **new**: The :func:`passlib.utils.saslprep` function may be useful
- for applications which need to normalize the unicode representation
- of passwords before they are hashed.
-
-Bugfixes
---------
- * Handle platform-specific error strings that may be returned by the
- :func:`!crypt` methods of some OSes.
-
- * Fixed rare ``'NoneType' object has no attribute 'decode'``
- error that sometimes occurred on platforms with a deviant implementation
- of :func:`!crypt`.
-
-Internal Changes
-----------------
- *The following changes should not affect most end users,
- and have been documented just to keep track of them:*
-
- .. currentmodule:: passlib.utils.handlers
-
- * Passlib is now source-compatible with Python 2.5+ and Python 3.x.
- It no longer requires the use of the :command:`2to3` command
- to translate it for Python 3.
-
- * The unittest suite has been rewritten. It handles a number of additional
- border cases, enforcing uniform behavior across all hashes, and
- even features the addition of some simplistic fuzz testing.
- It will take a bit longer to run though. While not perfect,
- statement coverage is at about 95%.
- Additionally, the hash test suite has been enhanced with many more
- test vectors across the board, including 8-bit test vectors.
-
- * The internal framework used to construct the hash classes (:mod:`passlib.utils.handlers`)
- was rewritten drastically. The new version provides stricter input checking,
- reduction in boilerplate code. *These changes should not affect any
- publically exposed routines*.
-
- - :class:`~passlib.utils.handlers.GenericHandler`'s
- ``strict`` keyword was removed, ``strict=True`` is now
- the class's default behavior: all values must be specified,
- and be within the correct bounds. The new keywords
- ``use_defaults`` and ``relaxed`` can be used to disable
- these two requirements.
-
- - Most of the private methods of :class:`~passlib.utils.handlers.GenericHandler`
- were renamed to begin with an underscore, to clarify their status;
- and turned into instance methods, to simplify the internals.
- (for example, :samp:`norm_salt` was renamed to :samp:`_norm_salt`).
-
- - :class:`~passlib.utils.handlers.StaticHandler` now derives from
- :class:`!GenericHandler`, and requires ``_calc_checksum()`` be
- implemented instead of ``encrypt()``. The old style is supported
- but deprecated, and support will be removed in Passlib 1.8.
-
- - Calls to :meth:`HasManyBackends.set_backend`
- should now use the string ``"any"`` instead of the value ``None``.
- ``None`` was deprecated in release 1.5, and is no longer supported.
-
- .. currentmodule:: passlib.utils
-
- * :mod:`!passlib.utils.h64` has been replaced by an instance of the
- new :class:`~passlib.utils.Base64Engine` class. This instance is
- imported under the same name, and has (mostly) the same interface;
- but should be faster, more flexible, and better unit-tested.
-
- * deprecated some unused support functions within :mod:`!passlib.utils`,
- they will be removed in release 1.7.
-
-.. _bcrypt-padding-issue:
-
-**1.5.3** (2011-10-08)
-======================
-
- Bugfix release -- fixes BCrypt padding/verification issue (:issue:`25`)
-
- This release fixes a single issue with Passlib's BCrypt support: Many
- BCrypt hashes generated by Passlib (<= 1.5.2) will not successfully verify
- under some of the other BCrypt implementations, such as OpenBSD's
- ``/etc/master.passwd``.
-
- *In detail:*
-
- BCrypt hashes contain 4 "padding" bits in the encoded salt, and Passlib
- (<= 1.5.2) generated salts in a manner which frequently set some of the
- padding bits to 1. While Passlib ignores these bits, many BCrypt
- implementations perform password verification in a way which rejects
- *all* passwords if any of the padding bits are set. Thus Passlib's
- BCrypt salt generation needed to be fixed to ensure compatibility,
- and a route provided to correct existing hashes already out in the wild
- :issue:`25`.
-
- *Changes in this release:*
-
- .. currentmodule:: passlib.context
-
- * BCrypt hashes generated by Passlib now have all padding bits cleared.
-
- * Passlib will continue to accept BCrypt hashes that have padding bits
- set, but when it encounters them, it will issue a :exc:`UserWarning`
- recommending that the hash should be fixed (see below).
-
- * Applications which use :meth:`CryptContext.verify_and_update` will
- have any such hashes automatically re-encoded the next time the user
- logs in.
-
- *To fix existing hashes:*
-
- If you have BCrypt hashes which might have their padding bits set,
- you can import :class:`!passlib.hash.bcrypt`, and
- call ``clean_hash = bcrypt.normhash(hash)``.
- This function will clear the padding bits of any BCrypt hashes,
- and should leave all other strings alone.
-
-**1.5.2** (2011-09-19)
-======================
-
- Minor bugfix release -- mainly Django-related fixes
-
- Hashes
-
- .. currentmodule:: passlib.hash
-
- * *bugfix:* :class:`django_des_crypt` now accepts all
- :data:`hash64 <passlib.utils.h64>` characters in its salts;
- previously it accepted only lower-case hexadecimal characters (:issue:`22`).
-
- * Additional unittests added for all
- standard :doc:`Django hashes </lib/passlib.hash.django_std>`.
-
- * :class:`django_des_crypt` now rejects hashes where salt and checksum
- containing mismatched salt characters.
-
- CryptContext
-
- .. currentmodule:: passlib.context
-
- * *bugfix:* fixed exception in :meth:`CryptPolicy.iter_config`
- that occurred when iterating over deprecation options.
-
- * Added documentation for the (mistakenly undocumented)
- :meth:`CryptContext.verify_and_update` method.
-
-**1.5.1** (2011-08-17)
-======================
-
- Minor bugfix release -- now compatible with Google App Engine.
-
- * *bugfix:* make ``passlib.hash.__loader__`` attribute writable -
- needed by Google App Engine (GAE) :issue:`19`.
-
- * *bugfix:* provide fallback for loading ``passlib/default.cfg``
- if :mod:`pkg_resources` is not present, such as for GAE :issue:`19`.
-
- * *bugfix:* fixed error thrown by CryptContext.verify
- when issuing min_verify_time warning :issue:`17`.
-
- * removed min_verify_time setting from custom_app_context,
- min_verify_time is too host & load dependant to be hardcoded :issue:`17`.
-
- * under GAE, disable all unittests which require writing to filesystem.
-
- * more unittest coverage for :mod:`passlib.apps` and :mod:`passlib.hosts`.
-
- * improved version datestamps in build script.
-
-**1.5** (2011-07-11)
-====================
-
-*"20% more unicode than the leading breakfast cereal"*
-
-The main new feature in this release is that
-Passlib now supports Python 3 (via the 2to3 tool).
-Everything has been recoded to have better separation
-between unicode and bytes, and to use unicode internally
-where possible.
-When run under Python 2, Passlib 1.5 attempts
-to provide the same behavior as Passlib 1.4;
-but when run under Python 3, most functions
-will return unicode instead of ascii bytes.
-
-Besides this major change, there have
-been some other additions:
-
-Hashes
-------
-
- * added support for Cryptacular's PBKDF2 format.
- * added support for the FSHP family of hashes.
- * added support for using BCryptor as BCrypt backend.
- * added support for all of Django's hash formats.
-
-CryptContext
-------------
-
- .. currentmodule:: passlib.context
-
- * interpolation deprecation:
-
- :meth:`CryptPolicy.from_path` and :meth:`CryptPolicy.from_string`
- now use :class:`!SafeConfigParser` instead of :class:`!ConfigParser`.
- This may cause some existing config files containing unescaped ``%``
- to result in errors; Passlib 1.5 will demote these to warnings,
- but any extant config files should be updated,
- as the errors will be fatal in Passlib 1.6.
-
- * added encoding keyword to :class:`!CryptPolicy`'s
- :meth:`!.from_path()`, :meth:`!.from_string`,
- and :meth:`!.to_string` methods.
-
- * both classes in :mod:`passlib.apache`
- now support specifying an encoding for the username/realm.
-
-Documentation
--------------
-
- * Password Hash API expanded to include explicit
- :ref:`unicode vs bytes policy <hash-unicode-behavior>`.
- * Added quickstart guide to documentation.
- * Various minor improvements.
-
-Internal Changes
-----------------
-
- * Added more handler utility functions to reduce code duplication.
- * Expanded kdf helpers in :mod:`!passlib.utils.pbkdf2`.
- * Removed deprecated parts of :mod:`passlib.utils.handlers`.
- * Various minor changes to
- :class:`passlib.utils.handlers.HasManyBackends`;
- main change is that multi-backend handlers now raise
- :exc:`~passlib.exc.MissingBackendError`
- if no backends are available.
-
- * Builtin tests now use :mod:`!unittest2` if available.
- * Setup script no longer requires distribute or setuptools.
- * added (undocumented, experimental) Django app
- for overriding Django's default hash format,
- see ``docs/lib/passlib.ext.django.rst`` for more.
-
-**1.4** (2011-05-04)
-====================
-
-This release contains a large number of changes, both large and small.
-It adds a number of PBKDF2-based schemes, better support
-for LDAP-format hashes, improved documentation,
-and faster load times. In detail...
-
-Hashes
-------
-
- * added LDAP ``{CRYPT}`` support for all hashes
- known to be supported by OS crypt()
- * added 3 custom PBKDF2 schemes for general use,
- as well as 3 LDAP-compatible versions.
- * added support for Dwayne Litzenberger's PBKDF2 scheme.
- * added support for Grub2's PBKDF2 hash scheme.
- * added support for Atlassian's PBKDF2 password hash
- * added support for all hashes used by the Roundup Issue Tracker
- * bsdi_crypt, sha1_crypt now check for OS crypt() support
- * ``salt_size`` keyword added to encrypt() method of all
- the hashes which support variable-length salts.
- * security fix: disabled unix_fallback's "wildcard password" support
- unless explicitly enabled by user.
-
-CryptContext
-------------
-
- * host_context now dynamically detects which formats
- OS crypt() supports, instead of guessing based on sys.platform.
- * added predefined context for Roundup Issue Tracker database.
- * added CryptContext.verify_and_update() convenience method,
- to make it easier to perform both operations at once.
- * *bugfix:* fixed NameError in category+min_verify_time border case
- * apps & hosts modules now use new
- :class:`LazyCryptContext` wrapper class -
- this should speed up initial import,
- and reduce memory by not loading unneeded hashes.
-
-Documentation
--------------
-
- * greatly expanded documentation on how to use CryptContexts.
- * roughly documented framework for writing & testing
- custom password handlers.
- * various minor improvements.
-
-Internals
----------
-
- * added generate_password() convenience method
- * refactored framework for building hash handlers,
- using new mixin-based system.
- * deprecated old handler framework - will remove in 1.5
- * deprecated list_to_bytes & bytes_to_list - not used, will remove in 1.5
-
-Other
------
-
- * password hash api - as part of cleaning up optional attributes
- specification, renamed a number of them to reduce ambiguity:
-
- - renamed *{xxx}_salt_chars* attributes -> *xxx_salt_size*
- - renamed *salt_charset* -> *salt_chars*
- - old attributes still present, but deprecated - will remove in 1.5
-
- * password hash api - tightened specifications for salt & rounds parameters,
- added support for hashes w/ no max salt size.
-
- * improved password hash api conformance tests
-
- * PyPy compatibility
-
-**1.3.1** (2011-03-28)
-======================
-
- Minor bugfix release.
-
- * bugfix: replaced "sys.maxsize" reference that was failing under py25
- * bugfix: fixed default_rounds>max_rounds border case that could
- cause ValueError during CryptContext.encrypt()
- * minor documentation changes
- * added instructions for building html documentation from source
-
-**1.3** (2011-03-25)
-====================
-
- First public release.
-
- * documentation completed
- * 99% unittest coverage
- * some refactoring and lots of bugfixes
- * added support for a number of additional password schemes:
- bigcrypt, crypt16, sun md5 crypt, nthash, lmhash, oracle10 & 11,
- phpass, sha1, generic hex digests, ldap digests.
-
-**1.2** (2011-01-06)
-====================
-
- .. note::
-
- For this and all previous versions, Passlib did not exist independently,
- but as a subpackage of *BPS*, a private & unreleased toolkit library.
-
- * many bugfixes
- * global registry added
- * transitional release for applications using BPS library.
- * first truly functional release since splitting from BPS library (see below).
-
-**1.0** (2009-12-11)
-====================
-
- * CryptContext & CryptHandler framework
- * added support for: des-crypt, bcrypt (via py-bcrypt), postgres, mysql
- * added unit tests
-
-**0.5** (2008-05-10)
-====================
-
- * initial production version
- * consolidated from code scattered across multiple applications
- * MD5-Crypt, SHA256-Crypt, SHA512-Crypt support
diff --git a/LICENSE b/LICENSE
index 4fa1c86..8b37500 100644
--- a/LICENSE
+++ b/LICENSE
@@ -4,6 +4,13 @@
Copyrights & Licenses
=====================
+Credits
+=======
+Passlib is primarily developed by Eli Collins.
+
+Special thanks to Darin Gordon for testing and
+feedback on the :mod:`passlib.totp` module.
+
License for Passlib
===================
Passlib is (c) `Assurance Technologies <http://www.assurancetechnologies.com>`_,
diff --git a/README b/README
index 542bd17..fdf1e15 100644
--- a/README
+++ b/README
@@ -15,7 +15,7 @@ providing full-strength password hashing for multi-user application.
* See the `documentation <https://passlib.readthedocs.io>`_
for details, installation instructions, and examples.
-* See the `changelog <https://passlib.readthedocs.io/en/stable/history.html>`_
+* See the `changelog <https://passlib.readthedocs.io/en/stable/history>`_
for a description of what's new in Passlib.
* Visit `PyPI <https://pypi.python.org/pypi/passlib>`_
diff --git a/docs/_fragments/insecure_hash_warning.rst b/docs/_fragments/insecure_hash_warning.rst
new file mode 100644
index 0000000..d5923cd
--- /dev/null
+++ b/docs/_fragments/insecure_hash_warning.rst
@@ -0,0 +1,9 @@
+.. rst-class:: block-title
+
+.. danger::
+
+ **This algorithm is not considered secure by modern standards.**
+ It should only be used when verifying existing hashes,
+ or when interacting with applications that require this format.
+ For new code, see the list of :ref:`recommended hashes <recommended-hashes>`.
+
diff --git a/docs/_fragments/trivial_hash_warning.rst b/docs/_fragments/trivial_hash_warning.rst
new file mode 100644
index 0000000..00049eb
--- /dev/null
+++ b/docs/_fragments/trivial_hash_warning.rst
@@ -0,0 +1,8 @@
+.. rst-class:: block-title
+
+.. danger::
+
+ **This algorithm is dangerously insecure by modern standards.**
+ It is trivially broken, and should not be used if at all possible.
+ For new code, see the list of :ref:`recommended hashes <recommended-hashes>`.
+
diff --git a/docs/contents.rst b/docs/contents.rst
index 0be84f5..6a1f2a2 100644
--- a/docs/contents.rst
+++ b/docs/contents.rst
@@ -6,8 +6,8 @@ Table Of Contents
:maxdepth: 4
Introduction <index>
- narrative
- reference
+ narr/index
+ lib/index
other
* :ref:`General Index <genindex>`
diff --git a/docs/history.rst b/docs/history.rst
deleted file mode 100644
index d6c5f48..0000000
--- a/docs/history.rst
+++ /dev/null
@@ -1 +0,0 @@
-.. include:: ../CHANGES
diff --git a/docs/history/1.5.rst b/docs/history/1.5.rst
new file mode 100644
index 0000000..006bf99
--- /dev/null
+++ b/docs/history/1.5.rst
@@ -0,0 +1,173 @@
+==========
+1.5 Series
+==========
+
+.. _bcrypt-padding-issue:
+
+**1.5.3** (2011-10-08)
+======================
+
+ Bugfix release -- fixes BCrypt padding/verification issue (:issue:`25`)
+
+ This release fixes a single issue with Passlib's BCrypt support: Many
+ BCrypt hashes generated by Passlib (<= 1.5.2) will not successfully verify
+ under some of the other BCrypt implementations, such as OpenBSD's
+ ``/etc/master.passwd``.
+
+ *In detail:*
+
+ BCrypt hashes contain 4 "padding" bits in the encoded salt, and Passlib
+ (<= 1.5.2) generated salts in a manner which frequently set some of the
+ padding bits to 1. While Passlib ignores these bits, many BCrypt
+ implementations perform password verification in a way which rejects
+ *all* passwords if any of the padding bits are set. Thus Passlib's
+ BCrypt salt generation needed to be fixed to ensure compatibility,
+ and a route provided to correct existing hashes already out in the wild
+ :issue:`25`.
+
+ *Changes in this release:*
+
+ .. currentmodule:: passlib.context
+
+ * BCrypt hashes generated by Passlib now have all padding bits cleared.
+
+ * Passlib will continue to accept BCrypt hashes that have padding bits
+ set, but when it encounters them, it will issue a :exc:`UserWarning`
+ recommending that the hash should be fixed (see below).
+
+ * Applications which use :meth:`CryptContext.verify_and_update` will
+ have any such hashes automatically re-encoded the next time the user
+ logs in.
+
+ *To fix existing hashes:*
+
+ If you have BCrypt hashes which might have their padding bits set,
+ you can import :class:`!passlib.hash.bcrypt`, and
+ call ``clean_hash = bcrypt.normhash(hash)``.
+ This function will clear the padding bits of any BCrypt hashes,
+ and should leave all other strings alone.
+
+**1.5.2** (2011-09-19)
+======================
+
+ Minor bugfix release -- mainly Django-related fixes
+
+ Hashes
+
+ .. currentmodule:: passlib.hash
+
+ * *bugfix:* :class:`django_des_crypt` now accepts all
+ :data:`hash64 <passlib.utils.h64>` characters in its salts;
+ previously it accepted only lower-case hexadecimal characters (:issue:`22`).
+
+ * Additional unittests added for all
+ standard :doc:`Django hashes </lib/passlib.hash.django_std>`.
+
+ * :class:`django_des_crypt` now rejects hashes where salt and checksum
+ containing mismatched salt characters.
+
+ CryptContext
+
+ .. currentmodule:: passlib.context
+
+ * *bugfix:* fixed exception in :meth:`CryptPolicy.iter_config`
+ that occurred when iterating over deprecation options.
+
+ * Added documentation for the (mistakenly undocumented)
+ :meth:`CryptContext.verify_and_update` method.
+
+**1.5.1** (2011-08-17)
+======================
+
+ Minor bugfix release -- now compatible with Google App Engine.
+
+ * *bugfix:* make ``passlib.hash.__loader__`` attribute writable -
+ needed by Google App Engine (GAE) :issue:`19`.
+
+ * *bugfix:* provide fallback for loading ``passlib/default.cfg``
+ if :mod:`pkg_resources` is not present, such as for GAE :issue:`19`.
+
+ * *bugfix:* fixed error thrown by CryptContext.verify
+ when issuing min_verify_time warning :issue:`17`.
+
+ * removed min_verify_time setting from custom_app_context,
+ min_verify_time is too host & load dependant to be hardcoded :issue:`17`.
+
+ * under GAE, disable all unittests which require writing to filesystem.
+
+ * more unittest coverage for :mod:`passlib.apps` and :mod:`passlib.hosts`.
+
+ * improved version datestamps in build script.
+
+**1.5** (2011-07-11)
+====================
+
+*"20% more unicode than the leading breakfast cereal"*
+
+The main new feature in this release is that
+Passlib now supports Python 3 (via the 2to3 tool).
+Everything has been recoded to have better separation
+between unicode and bytes, and to use unicode internally
+where possible.
+When run under Python 2, Passlib 1.5 attempts
+to provide the same behavior as Passlib 1.4;
+but when run under Python 3, most functions
+will return unicode instead of ascii bytes.
+
+Besides this major change, there have
+been some other additions:
+
+Hashes
+------
+
+ * added support for Cryptacular's PBKDF2 format.
+ * added support for the FSHP family of hashes.
+ * added support for using BCryptor as BCrypt backend.
+ * added support for all of Django's hash formats.
+
+CryptContext
+------------
+
+ .. currentmodule:: passlib.context
+
+ * interpolation deprecation:
+
+ :meth:`CryptPolicy.from_path` and :meth:`CryptPolicy.from_string`
+ now use :class:`!SafeConfigParser` instead of :class:`!ConfigParser`.
+ This may cause some existing config files containing unescaped ``%``
+ to result in errors; Passlib 1.5 will demote these to warnings,
+ but any extant config files should be updated,
+ as the errors will be fatal in Passlib 1.6.
+
+ * added encoding keyword to :class:`!CryptPolicy`'s
+ :meth:`!.from_path()`, :meth:`!.from_string`,
+ and :meth:`!.to_string` methods.
+
+ * both classes in :mod:`passlib.apache`
+ now support specifying an encoding for the username/realm.
+
+Documentation
+-------------
+
+ * Password Hash API expanded to include explicit
+ :ref:`unicode vs bytes policy <hash-unicode-behavior>`.
+ * Added quickstart guide to documentation.
+ * Various minor improvements.
+
+Internal Changes
+----------------
+
+ * Added more handler utility functions to reduce code duplication.
+ * Expanded kdf helpers in :mod:`!passlib.utils.pbkdf2`.
+ * Removed deprecated parts of :mod:`passlib.utils.handlers`.
+ * Various minor changes to
+ :class:`passlib.utils.handlers.HasManyBackends`;
+ main change is that multi-backend handlers now raise
+ :exc:`~passlib.exc.MissingBackendError`
+ if no backends are available.
+
+ * Builtin tests now use :mod:`!unittest2` if available.
+ * Setup script no longer requires distribute or setuptools.
+ * added (undocumented, experimental) Django app
+ for overriding Django's default hash format,
+ see ``docs/lib/passlib.ext.django.rst`` for more.
diff --git a/docs/history/1.6.rst b/docs/history/1.6.rst
new file mode 100644
index 0000000..6f3fac5
--- /dev/null
+++ b/docs/history/1.6.rst
@@ -0,0 +1,400 @@
+==========
+1.6 Series
+==========
+
+**1.6.5** (2015-08-04)
+======================
+
+ Fixed some minor bugs in the test suite which were causing erroneous test failures
+ (:issue:`57` and :issue:`58`). The passlib library itself is unchanged.
+
+.. rst-class:: toc-always-toggle
+
+**1.6.4** (2015-07-25)
+======================
+
+ This release rolls up assorted bug & compatibility fixes since 1.6.2.
+
+Bugfixes
+--------
+
+ * Correctly detect bcrypt 2.0. Previous releases were incorrectly detecting it as py-bcrypt,
+ causing spurious errors (:issue:`56`).
+
+ * CryptContext now accepts scheme names as unicode (:issue:`54`).
+
+ * :mod:`passlib.ext.django` now works correctly with Django 1.7-1.8. Previous
+ releases had various test failures (:issue:`52`).
+
+ * :class:`passlib.apache.HtpasswdFile` now recognizes bcrypt, sha256_crypt, sha512_crypt
+ hashes (:issue:`55`).
+
+BCrypt Changes
+--------------
+
+ A few changes have been made to the :class:`~passlib.hash.bcrypt` hash:
+
+ * It now supports the ``$2b$`` hash format.
+
+ * It will now issue a :exc:`~passlib.exc.PasslibSecurityWarning` if the active backend
+ is vulnerable to the :ref:`wraparound bug <bsd-wraparound-bug>`,
+ and automatically enable a workaround (py-bcrypt is known to be vulnerable as of v0.4).
+
+ * It will throw a :exc:`~passlib.exc.PasslibSecurityError` if the active backend
+ is vulnerable to the :ref:`8-bit bug <crypt-blowfish-bug>` (none of Passlib's
+ backends are known to be vulnerable as of 2015-07).
+
+ * Updated documentation to indicate the cffi-based `bcrypt <https://pypi.python.org/pypi/bcrypt>`_
+ library is now the recommended bcrypt backend.
+
+ * Backend capability detection code refactored to rely on runtime detection
+ rather than hardcoded information.
+
+Other Changes
+-------------
+
+ * Source repo's ``tox.ini`` updated. Now assumes python3 by default, and refactored test
+ environments to more cleanly delineate the different setups being tested.
+
+ * Passlib releases are now published as wheels instead of eggs.
+
+**1.6.3** (2015-07-25)
+======================
+
+ This was relabeled as **1.6.4** due to PyPI upload issues.
+
+**1.6.2** (2013-12-26)
+======================
+
+ Minor changes & compatibility fixes
+
+ * Re-tuned the :attr:`~passlib.ifc.PasswordHash.default_rounds` values for all of the hashes.
+
+ * Added the new :doc:`bcrypt_sha256 </lib/passlib.hash.bcrypt_sha256>` hash,
+ which wraps BCrypt using SHA256 in order to work around BCrypt's password size limitations
+ (:issue:`43`).
+
+ * :doc:`passlib.hash.bcrypt </lib/passlib.hash.bcrypt>`:
+ Added support for the `bcrypt <https://pypi.python.org/pypi/bcrypt>`_
+ library as one of the possible bcrypt backends that will be used if available.
+ (:issue:`49`)
+
+ * :mod:`passlib.ext.django`: Passlib's Django extension
+ (and it's related hashes and unittests) have been updated to handle
+ some minor API changes in Django 1.5-1.6. They should now be compatible with Django 1.2 and up.
+ (:issue:`50`)
+
+**1.6.1** (2012-08-02)
+======================
+
+ Minor bugfix release
+
+ * *bugfix*: Various :class:`~passlib.context.CryptContext` methods
+ would incorrectly raise :exc:`TypeError` if passed a :class:`!unicode`
+ user category under Python 2. For consistency,
+ :class:`!unicode` user category values are now encoded to ``utf-8`` :class:`bytes` under Python 2.
+
+ * *bugfix*: Reworked internals of the :class:`CryptContext` config compiler
+ to fix a couple of border cases (:issue:`39`):
+
+ - It will now throw a :exc:`ValueError`
+ if the :ref:`default <context-default-option>` scheme is marked as
+ :ref:`deprecated <context-deprecated-option>`.
+ - If no default scheme is specified, it will use the first
+ *non-deprecated* scheme.
+ - Finally, it will now throw a :exc:`ValueError` if all schemes
+ are marked as deprecated.
+
+ * *bugfix*: FreeBSD 8.3 added native support for :class:`~passlib.hash.sha256_crypt` --
+ updated Passlib's unittests and documentation accordingly (:issue:`35`).
+
+ * *bugfix:* Fixed bug which caused some :mod:`!passlib.apache` unittests to fail
+ if mtime resolution >= 1 second (:issue:`35`).
+
+ * *bugfix:* Fixed minor bug in :mod:`!passlib.registry`, should now work correctly under Python 3.3.
+
+ * Various documentation updates and corrections.
+
+**1.6** (2012-05-01)
+====================
+
+Overview
+--------
+
+ Welcome to Passlib 1.6.
+
+ The main goal of this release was to clean up the codebase, tighten input
+ validation, and simplify the publically exposed interfaces. This release also
+ brings a number of other improvements: 10 or so new hash algorithms,
+ additional security precautions for the existing algorithms,
+ a number of speed improvements, and updated documentation.
+
+Deprecated APIs
+...............
+ In order to improve the publically exposed interface,
+ some of the more cumbersome and less-used functions in Passlib
+ have been deprecated / renamed. This should not affect 99% of applications.
+ That said, all the deprecated interfaces are still present, and will continue
+ to be supported for at least one more major release.
+ To help with migration, all deprecated functions should issue an informative
+ :exc:`DeprecationWarning` when they are invoked, detailing their suggested replacement.
+ The following interfaces have changed:
+
+ * The semi-internal :class:`!CryptPolicy` class has been deprecated
+ in its entirety. All functionality has been rolled into the
+ parent :class:`!CryptContext` class (see :ref:`below <crypt-policy-deprecated>` for more).
+
+ * The interface of the :mod:`passlib.apache` classes has been improved:
+ some confusing methods and options have been renamed, some new
+ constructors and other functions have been added.
+
+ * The (undocumented) :mod:`!passlib.win32` module has been deprecated,
+ all of its functionality is now offered through the
+ :doc:`lmhash </lib/passlib.hash.lmhash>` and :doc:`nthash </lib/passlib.hash.nthash>`
+ algorithms.
+
+New Hashes
+----------
+ The release adds support for a number of hash algorithms:
+
+ :doc:`cisco_pix </lib/passlib.hash.cisco_pix>`, :doc:`cisco_type7 </lib/passlib.hash.cisco_type7>`
+ Two hash formats frequently found on various
+ Cisco devices *(for Cisco Type 5 hashes, see*
+ :doc:`md5_crypt </lib/passlib.hash.md5_crypt>` *).*
+
+ :ref:`django_pbkdf2_sha256 <django-1.4-hashes>`, :ref:`django_pbkdf2_sha1 <django-1.4-hashes>`, :ref:`django_bcrypt <django-1.4-hashes>`
+ All three of the new hash schemes introduced in Django 1.4.
+
+ :doc:`lmhash </lib/passlib.hash.lmhash>`, :doc:`nthash </lib/passlib.hash.nthash>`
+ Microsoft's legacy "Lan Manager" hash, and the replacement
+ NT password hash. *(the old* ``nthash`` *algorithm in Passlib 1.5 has been renamed to*
+ :class:`~passlib.hash.bsd_nthash` *, to reflect its lineage)*.
+
+ :doc:`msdcc </lib/passlib.hash.msdcc>`, :doc:`msdcc2 </lib/passlib.hash.msdcc2>`
+ Microsoft Windows' Domain Cached Credentials, versions 1 and 2.
+ These algorithms also go by the names "DCC", "MSCache", and "MSCash".
+
+ :doc:`mssql2000 </lib/passlib.hash.mssql2000>`, :doc:`mssql2005 </lib/passlib.hash.mssql2005>`
+ Hash algorithms used by MS SQL Server 2000 and later.
+
+ :doc:`scram </lib/passlib.hash.scram>`
+ A hash format added specifically for storing the complex digest
+ information needed to authenticate a user via the SCRAM protocol
+ (:rfc:`5802`). It can also be used in the same way as any other
+ password hash in Passlib.
+
+Existing Hashes
+---------------
+ Additionally, the following new features have been added to the existing hashes:
+
+ .. _password-size-limit:
+
+ *Password Size Limit*
+ All hashes in Passlib will now throw :exc:`~passlib.exc.PasswordSizeError`
+ if handed a password that's larger than 4096 characters.
+
+ This limit should be larger than any reasonable password size,
+ and prevents various things including DOS abuses, and exploitation
+ of OSes with a buggy :func:`!crypt` implementation.
+ See :exc:`~passlib.exc.PasswordSizeError` for how to change this limit.
+
+ .. _consteq-issue:
+
+ *Constant Time Comparison*
+ All hash comparisons in Passlib now use the "constant time" [#consteq]_
+ comparison function :func:`~passlib.utils.consteq`, instead
+ of ``==``.
+
+ This change is motivated a well-known `hmac timing attack <http://rdist.root.org/2009/05/28/timing-attack-in-google-keyczar-library/>`_
+ which exploits short-circuit string comparisons.
+ While this attack is not currently feasible against
+ most password hashes, some of the weaker unsalted
+ hashes supported by Passlib may be vulnerable; and this
+ change has been made preventatively to all of them.
+
+ .. [#consteq] "constant time" is a misnomer, it actually takes ``THETA(len(righthand_value))`` time.
+
+ .. _strict-parameters:
+
+ *Strict Parameters*
+ Previous releases of Passlib would silently correct any invalid values
+ (such as ``rounds`` parameters that were out of range). This is was deemed
+ undesirable, as it leaves developers unaware they are requesting
+ an incorrect (and potentially insecure) value.
+
+ Starting with this release, providing invalid values to
+ :meth:`PasswordHash.encrypt <passlib.ifc.PasswordHash.encrypt>`
+ will result in a :exc:`ValueError`. However, most hashes now accept
+ an optional ``relaxed=True`` keyword, which causes Passlib
+ to try and correct invalid values, and if successful,
+ issue a :exc:`~passlib.exc.PasslibHashWarning` instead.
+ These warnings can then be filtered if desired.
+
+ :doc:`bcrypt </lib/passlib.hash.bcrypt>`
+ The BCrypt hash now supports the `crypt_blowfish <http://www.openwall.com/crypt/>`_ project's
+ ``$2y$`` hash prefix.
+
+ On an unrelated note, Passlib now offers an (experimental) pure-python
+ implementation of BCrypt. Unfortunately, it's still *WAY* too slow to be
+ suitable for production use; and is disabled by default.
+ If you really need it, see the BCrypt :ref:`documentation <bcrypt-backends>`
+ for how to enable it.
+
+ :doc:`bsdi_crypt </lib/passlib.hash.bsdi_crypt>`
+ BSDi-Crypt will now issue a :exc:`~passlib.exc.PasslibSecurityWarning`
+ if an application requests an even number of rounds, due to
+ a known weakness in DES. Existing hashes with an even number of rounds will
+ now be flagged by :meth:`CryptContext.needs_update() <passlib.context.CryptContext.needs_update>`.
+
+ :doc:`ldap_salted_{digest} </lib/passlib.hash.ldap_std>`
+ The LDAP salted digests now support salts of any size
+ from 4-16 bytes, though they still default to 4 (:issue:`30`).
+
+ :doc:`md5_crypt </lib/passlib.hash.md5_crypt>`, :doc:`sha256_crypt </lib/passlib.hash.md5_crypt>`, :doc:`sha512_crypt </lib/passlib.hash.md5_crypt>`
+ The builtin implementation of these hashes has been
+ sped up by about 25%, using an additional pre-computation step.
+
+ :doc:`unix_disabled </lib/passlib.hash.unix_disabled>`
+ The :class:`!unix_fallback` handler has been deprecated,
+ and will be removed in Passlib 1.8.
+ Applications should use the stricter-but-equivalent
+ :class:`!unix_disabled` handler instead.
+
+ This most likely only affects internal Passlib code.
+
+.. _crypt-policy-deprecated:
+
+CryptContext
+------------
+
+ .. currentmodule:: passlib.context
+
+ The :ref:`CryptContext <context-reference>` class has had a thorough
+ internal overhaul. While the primary interface has not changed
+ at all, the internals are much stricter about input validation,
+ common methods have shorter code-paths, and the
+ construction and introspection of :class:`!CryptContext` objects
+ has been greatly simplified.
+ Changes include:
+
+ * All new (and hopefully clearer) :ref:`tutorial <context-tutorial>`
+ and :ref:`reference <context-reference>` documentation.
+
+ * The :class:`CryptPolicy` class and the :attr:`!CryptContext.policy` attribute have been deprecated.
+
+ This was a semi-internal class, which most applications
+ were not involved with at all, but to be conservative about
+ breaking things, the existing CryptPolicy interface
+ will remain in-place and supported until Passlib 1.8.
+
+ All of the functionality of this class has been rolled into
+ :class:`!CryptContext` itself, so there's one less class to remember.
+ Many of the methods provided by :class:`!CryptPolicy` are now
+ :class:`!CryptContext` methods, most with the same name and call syntax.
+ Information on migrating existing code can be found in
+ the deprecation warnings issued by the class itself,
+ and in the :class:`CryptPolicy` documentation.
+
+ * Two new class constructors have been added (:meth:`CryptContext.from_path`
+ and :meth:`CryptContext.from_string`) to aid in loading CryptContext objects
+ directly from a configuration file.
+
+ * The :ref:`deprecated <context-deprecated-option>` keyword
+ can now be set to the special string ``"auto"``; which will
+ automatically deprecate all schemes except for the default one.
+
+ * The :ref:`min_verify_time <context-min-verify-time-option>` keyword
+ has been deprecated, will be ignored in release 1.7, and will be removed in release 1.8.
+ It was never very useful, and now complicates the internal code needlessly.
+
+ * All string parsing now uses stdlib's :class:`!SafeConfigParser`.
+
+ Previous releases used the original :class:`!ConfigParser` interpolation;
+ which was deprecated in Passlib 1.5, and has now been removed.
+ This should only affect strings which contained raw ``%`` characters,
+ they will now need to be escaped via ``%%``.
+
+Other Modules
+-------------
+
+ * The api for the :mod:`passlib.apache` module has been updated
+ to add more flexibility, and to fix some ambiguous method
+ and keyword names. The old interface is still supported, but deprecated,
+ and will be removed in Passlib 1.8.
+
+ * Added the :data:`~passlib.apps.django14_context` preset to the
+ the :mod:`!passlib.apps` module. this preconfigured CryptContext
+ object should support all the hashes found in a typical Django 1.4
+ deployment.
+
+ * **new**: Added :mod:`passlib.ext.django`, a Django plugin which can be used to
+ override Django's password hashing framework with a custom Passlib
+ policy (an undocumented beta version of this was present in the 1.5 release).
+
+ * **new**: The :func:`passlib.utils.saslprep` function may be useful
+ for applications which need to normalize the unicode representation
+ of passwords before they are hashed.
+
+Bugfixes
+--------
+ * Handle platform-specific error strings that may be returned by the
+ :func:`!crypt` methods of some OSes.
+
+ * Fixed rare ``'NoneType' object has no attribute 'decode'``
+ error that sometimes occurred on platforms with a deviant implementation
+ of :func:`!crypt`.
+
+Internal Changes
+----------------
+ *The following changes should not affect most end users,
+ and have been documented just to keep track of them:*
+
+ .. currentmodule:: passlib.utils.handlers
+
+ * Passlib is now source-compatible with Python 2.5+ and Python 3.x.
+ It no longer requires the use of the :command:`2to3` command
+ to translate it for Python 3.
+
+ * The unittest suite has been rewritten. It handles a number of additional
+ border cases, enforcing uniform behavior across all hashes, and
+ even features the addition of some simplistic fuzz testing.
+ It will take a bit longer to run though. While not perfect,
+ statement coverage is at about 95%.
+ Additionally, the hash test suite has been enhanced with many more
+ test vectors across the board, including 8-bit test vectors.
+
+ * The internal framework used to construct the hash classes (:mod:`passlib.utils.handlers`)
+ was rewritten drastically. The new version provides stricter input checking,
+ reduction in boilerplate code. *These changes should not affect any
+ publically exposed routines*.
+
+ - :class:`~passlib.utils.handlers.GenericHandler`'s
+ ``strict`` keyword was removed, ``strict=True`` is now
+ the class's default behavior: all values must be specified,
+ and be within the correct bounds. The new keywords
+ ``use_defaults`` and ``relaxed`` can be used to disable
+ these two requirements.
+
+ - Most of the private methods of :class:`~passlib.utils.handlers.GenericHandler`
+ were renamed to begin with an underscore, to clarify their status;
+ and turned into instance methods, to simplify the internals.
+ (for example, :samp:`norm_salt` was renamed to :samp:`_norm_salt`).
+
+ - :class:`~passlib.utils.handlers.StaticHandler` now derives from
+ :class:`!GenericHandler`, and requires ``_calc_checksum()`` be
+ implemented instead of ``encrypt()``. The old style is supported
+ but deprecated, and support will be removed in Passlib 1.8.
+
+ - Calls to :meth:`HasManyBackends.set_backend`
+ should now use the string ``"any"`` instead of the value ``None``.
+ ``None`` was deprecated in release 1.5, and is no longer supported.
+
+ .. currentmodule:: passlib.utils
+
+ * :mod:`!passlib.utils.h64` has been replaced by an instance of the
+ new :class:`~passlib.utils.Base64Engine` class. This instance is
+ imported under the same name, and has (mostly) the same interface;
+ but should be faster, more flexible, and better unit-tested.
+
+ * deprecated some unused support functions within :mod:`!passlib.utils`,
+ they will be removed in release 1.7.
diff --git a/docs/history/1.7.rst b/docs/history/1.7.rst
new file mode 100644
index 0000000..dce9ac1
--- /dev/null
+++ b/docs/history/1.7.rst
@@ -0,0 +1,305 @@
+.. _whats-new:
+
+==========
+1.7 Series
+==========
+
+.. seealso::
+
+ The `Roadmap <https://bitbucket.org/ecollins/passlib/wiki/Roadmap>`_
+ for a list of future changes that may impact applications.
+
+.. rst-class:: emphasize-children toc-always-open
+
+**1.7.0** (NOT YET RELEASED)
+============================
+
+Overview
+--------
+
+ *Welcome to Passlib 1.7!*
+
+ This release includes a number of new features, cleans up
+ some long-standing design issues, and contains a number of internal
+ improvements; all part of the roadmap towards a leaner and simpler Passlib 2.0.
+
+ *Highlights include:*
+
+ * Support for :class:`~passlib.hash.argon2` and
+ :class:`~passlib.hash.scrypt` hashes.
+
+ .. currentmodule:: passlib.ifc
+
+ * The misnamed :meth:`PasswordHash.encrypt` method is deprecated, new code should
+ now call :meth:`PasswordHash.hash` instead. This is part of a much
+ larger project to clean up passlib's password hashing API,
+ including the new :meth:`PasswordHash.using` factory constructor.
+
+ * TOTP Two-Factor Authentications helpers in the :mod:`passlib.totp` module.
+
+ * Large speedup of the internal PBKDF2 routines.
+
+Requirements
+------------
+
+ * **Passlib now requires Python 2.6, 2.7, or >= 3.3**.
+ Support for Python versions 2.5 and 3.0 through 3.2 have been dropped.
+ Support for PyPy 1.x has also been dropped.
+
+ * The :mod:`passlib.ext.django` extension now requires Django 1.8 or better.
+ Django 1.7 and earlier are no longer supported.
+
+New Features
+------------
+
+*New Hashes*
+
+ * :doc:`passlib.hash.argon2 </lib/passlib.hash.argon2>` --
+ Support for the Argon2 password hash (:issue:`69`).
+
+ * :doc:`passlib.hash.scrypt </lib/passlib.hash.scrypt>` --
+ New password hash format which uses the SCrypt KDF (:issue:`8`).
+
+ * :doc:`passlib.hash.cisco_asa </lib/passlib.hash.cisco_asa>` --
+ Support for Cisco ASA 7.0 and newer hashes (:issue:`51`).
+ *Note: this should be considered experimental, and needs verification
+ of it's test vectors.*
+
+*New Modules*
+
+ * New :mod:`passlib.totp` module provides full support for TOTP tokens
+ on both client and server side. This module contains both low-level primitives,
+ and high-level helpers for persisting and tracking client state.
+
+ * New :mod:`passlib.pwd` module added to aid in password generation.
+ Features support for alphanumeric passwords, or generation
+ of phrases using the EFF's password generation wordlist.
+
+*CryptContext Features*
+
+ * The :class:`~passlib.context.CryptContext` object now has helper
+ methods for dealing with hashes representing
+ :ref:`disabled accounts <context-disabled-hashes>` (:issue:`45`).
+
+ * The :class:`~passlib.context.CryptContext` object now supports
+ a :ref:`harden_verify <context-harden-verify-option>` option,
+ allowing applications to introduce a delay in verification
+ to help prevent attackers discovering weak or missing hashes
+ through timing attacks.
+
+ * All hashers which truncate passwords (e.g. :class:`~passlib.hash.bcrypt`
+ and :class:`~passlib.hash.des_crypt`) can now be configured to raise
+ a :exc:`~passlib.exc.PasswordTruncateError` when a overly-large password is provided.
+ This configurable via (for example) ``bcrypt.using(truncate_error=True).hash(secret)``,
+ or globally as an option to CryptContext (:issue:`59`).
+
+*Cryptographic Backends*
+
+ * The :func:`~passlib.crypto.digest.pbkdf2_hmac` function and all PBKDF2-based
+ hashes have been sped up by ~20% compared to Passlib 1.6. For an even greater
+ speedup, it will now take advantage of the external `fastpbk2 <https://pypi.python.org/pypi/fastpbkdf2>`_
+ library, or stdlib's :func:`hashlib.pbkdf2_hmac` (when available).
+
+Bugfixes
+--------
+ * :class:`~passlib.hash.bcrypt`: Passlib will now detect and work around
+ a fatal concurrency bug in py-bcrypt 0.2 and earlier
+ (a :exc:`~passlib.exc.PasslibSecurityWarning` will also be issued).
+ Nevertheless, users are *strongly* encouraged to upgrade to py-bcrypt 0.3
+ or another bcrypt library if you are using the
+ :doc:`bcrypt </lib/passlib.hash.bcrypt>` hash.
+
+ * :class:`~passlib.CryptContext` instances now pass contextual keywords (such as `"user"`)
+ to the hashes that support them, but ignore them for hashes that don't (:issue:`63`).
+
+ * The :mod:`passlib.apache` htpasswd helpers now preserve blank lines and comments,
+ rather than throwing a parse error (:issue:`73`).
+
+ * :mod:`passlib.ext.django` and unittests: compatibility fixes for Django 1.9,
+ and some internal cleanups (:issue:`68`).
+
+ * The :class:`~passlib.hash.django_disabled` hash now appends
+ a 40-char alphanumeric string, to match Django's behavior.
+
+Other Changes
+-------------
+
+*Public Changes*
+
+* :class:`~passlib.hash.bcrypt` and :class:`~passlib.hash.bcrypt_sha256`
+ now default to the "2b" format.
+
+* :class:`passlib.apache.HtpasswdFile` has been updated to support all of Apache 2.4's
+ hash schemes, as well as all host OS crypt formats; allowing for much more
+ secure hashes in htpasswd files. You can now specify if the default hash
+ should be compatible with apache 2.2 / 2.4, and host-specific or portable.
+ See the ``default_schemes`` keyword for details.
+
+* Large parts of the documentation have been rewritten, to separate
+ tutorial & api reference content, and provide more detail on various features.
+
+* Official documentation is now at https://passlib.readthedocs.io
+
+*Internal Changes*
+
+ .. currentmodule:: passlib.ifc
+
+ * The majority of CryptContext's internal rounds handling & migration code has been
+ moved to the password hashes themselves, taking advantage of the new :meth:`PasswordHash.using`
+ and :meth:`PasswordHash.needs_update` methods.
+
+ This allows much more flexibility when configuring a hasher directly,
+ as well making it easier for CryptContext to support hash-specific parameters.
+
+ * The shared :class:`!PasswordHash` unittests now check all hash handlers for
+ basic thread-safety (motivated by the pybcrypt 0.2 concurrency bug).
+
+ * :func:`~passlib.utils.consteq` is now wraps stdlib's :func:`hmac.compare_digest`
+ when available (python 2.7.11, python 3.3 and up).
+
+.. _encrypt-method-cleanup:
+
+Deprecations
+------------
+As part of a long-range plan to restructure and simplify both the API and the internals of Passlib,
+a number of methods have been deprecated & replaced. The eventually goal is a large cleanup
+and overhaul as part of Passlib 2.0. There will be at least one more 1.x version
+before Passlib 2.0, to provide a final transitional release.
+
+Password Hash API Deprecations
+..............................
+ .. currentmodule:: passlib.ifc
+
+ As part of this cleanup, the :class:`~passlib.ifc.PasswordHash` API (used by all hashes in passlib),
+ has had a number of changes:
+
+ .. rst-class:: float-right
+
+ .. seealso::
+
+ :ref:`hash-tutorial`, which walks through using the new hasher interface.
+
+ * **[major]** The :meth:`!PasswordHash.encrypt` method
+ has been renamed to :meth:`PasswordHash.hash`,
+ to clarify that it's performing one-way hashing rather than reversiable encryption.
+ A compatibility alias will remain in place until Passlib 2.0.
+ This should fix the longstanding :issue:`21`.
+
+ * **[major]** Passing explicit configuration options to the :meth:`!PasswordHash.encrypt` method
+ (now called :meth:`PasswordHash.hash`) is deprecated.
+ To provide settings such as ``rounds`` and ``salt_size``, callers
+ should use the new :meth:`PasswordHash.using`
+ method, which generates a new hasher with a customized configuration.
+
+ >>> # for example, instead of this:
+ >>> sha256_crypt.encrypt("secret", rounds=12345)
+
+ >>> # callers should now use:
+ >>> sha256_crypt.using(rounds=12345).hash("secret")
+
+ Support for the old syntax will be removed in Passlib 2.0.
+
+ .. note::
+
+ This doesn't apply to contextual options such as :class:`~passlib.hash.cisco_pix`'s
+ ``user`` keyword, which should still be passed into the :meth:`!hash` method.
+
+ * **[minor]** The little-used :meth:`PasswordHash.genhash` and
+ :meth:`PasswordHash.genconfig` methods have been deprecated.
+ Compatibility aliases will remain in place until Passlib 2.0,
+ at which point they will be removed entirely.
+
+Crypt Context API Deprecations
+..............................
+ .. currentmodule:: passlib.context
+
+ Applications which use passlib's :class:`~passlib.context.CryptContext` should not be
+ greatly affected by this release; only one major deprecation was made:
+
+ * **[major]** To match the :class:`!PasswordHash` API changes above,
+ the :meth:`!CryptContext.encrypt` method was renamed to :meth:`CryptContext.hash`.
+ A compatibility alias will remain until Passlib 2.0.
+
+ A fewer internal options and infrequently used features have been deprecated:
+
+ * **[minor]** :meth:`CryptContext.hash`, :meth:`~CryptContext.verify`,
+ :meth:`~CryptContext.verify_and_update`, and
+ :meth:`~CryptContext.needs_update`:
+ The ``scheme`` keyword is now deprecated; support will be removed in Passlib 2.0.
+
+ * **[minor]** :meth:`CryptContext.hash`: Passing
+ settings keywords to :meth:`!hash` such as ``rounds`` and ``salt`` is deprecated.
+ Code should now get ahold of the default hasher, and invoke it explicitly::
+
+ >>> # for example, calls that did this:
+ >>> context.hash(secret, rounds=1234)
+
+ >>> # should use this instead:
+ >>> context.handler().using(rounds=1234).hash(secret)
+
+ * **[minor]** The ``vary_rounds`` option has been deprecated,
+ and will be removed in Passlib 2.0. It provided very little security benefit,
+ and was judged not worth the additional code complexity it requires.
+
+ * **[minor]** The special wildcard ``all`` scheme name
+ has been deprecated, and will be removed in Passlib 2.0. The only legitimate use
+ was to support ``vary_rounds``, which itself will be removed in 2.0.
+
+Other Deprecations
+..................
+ A few other assorted deprecations have been made:
+
+ * The :func:`passlib.utils.generate_secret` function has been deprecated
+ in favor of the new :mod:`passlib.pwd` module, and the old function will be removed
+ in Passlib 2.0.
+
+ * Most of passlib's internal cryptography helpers have been moved from
+ :mod:`passlib.utils` to :mod:`passlib.crypto`, and the APIs refactored.
+ This allowed unification of various hash management routines,
+ some speed ups to the HMAC and PBKDF2 primitives, and opens up the architecture
+ to support more optional backend libraries.
+
+ Compatibility wrappers will be kept in place at the old location until Passlib 2.0.
+
+ * Some deprecations and internal changes have been made to the :mod:`passlib.utils.handlers`
+ module, which provides the common framework Passlib uses to implement hashers.
+
+ .. warning::
+
+ Developers who are importing from the :mod:`!passlib.utils.handlers` module directly are strongly encouraged
+ to contact the Passlib `mailing list <http://groups.google.com/group/passlib-users>`_.
+ Backwards-incompatible relocations will occur in the Passlib 1.8 / 1.9 releases.
+
+Backwards Incompatibilities
+---------------------------
+Changes in existing behavior:
+
+ * **[moderate]** :mod:`passlib.apache`: New hashes generated by :class:`~passlib.apache.HtpasswdFile` now use the strongest
+ algorithm available on the host, rather than one that is guaranteed to be portable.
+ Applications can explicitly set ``HtPasswdFile(default_scheme="portable")`` to restore the old behavior.
+
+ * **[minor]** M2Crypto no longer used to accelerate pbkdf2-hmac-sha1; applications relying on this
+ to speed up :class:`~passlib.hash.pbkdf2_sha1` should install
+ `fastpbkdf2 <https://pypi.python.org/pypi/fastpbkdf2>`_.
+
+Scheduled removal of features:
+
+ * **[minor]** :mod:`passlib.context`: The :ref:`min_verify_time <context-min-verify-time-option>` keyword
+ that was deprecated in release 1.6, is now completely ignored.
+ Support will be removed entirely in release 1.8.
+ See the new :ref:`harden_verify <context-harden-verify-option>` keyword
+ that replaces it.
+
+ * **[trivial]** :mod:`passlib.hash`: The internal :meth:`!PasswordHash.parse_rounds` method, deprecated in 1.6, has been removed.
+
+Minor incompatibilities:
+
+ * **[minor]** :mod:`passlib.hash`: The little-used method :meth:`~passlib.ifc.PasswordHash.genconfig`
+ will now always return a valid hash, rather than a truncated configuration
+ string or ``None``.
+
+ * **[minor]** :mod:`passlib.hash`: The little-used method :meth:`~passlib.ifc.PasswordHash.genhash` no longer accepts
+ ``None`` as a config argument.
+
+ * **[trivial]** :func:`passlib.utils.pbkdf2.pbkdf2` no longer supports custom PRF callables.
+ this was an unused feature, and prevented some useful optimizations.
diff --git a/docs/history/ancient.rst b/docs/history/ancient.rst
new file mode 100644
index 0000000..797f584
--- /dev/null
+++ b/docs/history/ancient.rst
@@ -0,0 +1,126 @@
+=============
+1.4 & Earlier
+=============
+
+**1.4** (2011-05-04)
+====================
+
+This release contains a large number of changes, both large and small.
+It adds a number of PBKDF2-based schemes, better support
+for LDAP-format hashes, improved documentation,
+and faster load times. In detail...
+
+Hashes
+------
+
+ * added LDAP ``{CRYPT}`` support for all hashes
+ known to be supported by OS crypt()
+ * added 3 custom PBKDF2 schemes for general use,
+ as well as 3 LDAP-compatible versions.
+ * added support for Dwayne Litzenberger's PBKDF2 scheme.
+ * added support for Grub2's PBKDF2 hash scheme.
+ * added support for Atlassian's PBKDF2 password hash
+ * added support for all hashes used by the Roundup Issue Tracker
+ * bsdi_crypt, sha1_crypt now check for OS crypt() support
+ * ``salt_size`` keyword added to encrypt() method of all
+ the hashes which support variable-length salts.
+ * security fix: disabled unix_fallback's "wildcard password" support
+ unless explicitly enabled by user.
+
+CryptContext
+------------
+
+ * host_context now dynamically detects which formats
+ OS crypt() supports, instead of guessing based on sys.platform.
+ * added predefined context for Roundup Issue Tracker database.
+ * added CryptContext.verify_and_update() convenience method,
+ to make it easier to perform both operations at once.
+ * *bugfix:* fixed NameError in category+min_verify_time border case
+ * apps & hosts modules now use new
+ :class:`LazyCryptContext` wrapper class -
+ this should speed up initial import,
+ and reduce memory by not loading unneeded hashes.
+
+Documentation
+-------------
+
+ * greatly expanded documentation on how to use CryptContexts.
+ * roughly documented framework for writing & testing
+ custom password handlers.
+ * various minor improvements.
+
+Internals
+---------
+
+ * added generate_password() convenience method
+ * refactored framework for building hash handlers,
+ using new mixin-based system.
+ * deprecated old handler framework - will remove in 1.5
+ * deprecated list_to_bytes & bytes_to_list - not used, will remove in 1.5
+
+Other
+-----
+
+ * password hash api - as part of cleaning up optional attributes
+ specification, renamed a number of them to reduce ambiguity:
+
+ - renamed *{xxx}_salt_chars* attributes -> *xxx_salt_size*
+ - renamed *salt_charset* -> *salt_chars*
+ - old attributes still present, but deprecated - will remove in 1.5
+
+ * password hash api - tightened specifications for salt & rounds parameters,
+ added support for hashes w/ no max salt size.
+
+ * improved password hash api conformance tests
+
+ * PyPy compatibility
+
+**1.3.1** (2011-03-28)
+======================
+
+ Minor bugfix release.
+
+ * bugfix: replaced "sys.maxsize" reference that was failing under py25
+ * bugfix: fixed default_rounds>max_rounds border case that could
+ cause ValueError during CryptContext.encrypt()
+ * minor documentation changes
+ * added instructions for building html documentation from source
+
+**1.3** (2011-03-25)
+====================
+
+ First public release.
+
+ * documentation completed
+ * 99% unittest coverage
+ * some refactoring and lots of bugfixes
+ * added support for a number of additional password schemes:
+ bigcrypt, crypt16, sun md5 crypt, nthash, lmhash, oracle10 & 11,
+ phpass, sha1, generic hex digests, ldap digests.
+
+**1.2** (2011-01-06)
+====================
+
+ .. note::
+
+ For this and all previous versions, Passlib did not exist independently,
+ but as a subpackage of *BPS*, a private & unreleased toolkit library.
+
+ * many bugfixes
+ * global registry added
+ * transitional release for applications using BPS library.
+ * first truly functional release since splitting from BPS library (see below).
+
+**1.0** (2009-12-11)
+====================
+
+ * CryptContext & CryptHandler framework
+ * added support for: des-crypt, bcrypt (via py-bcrypt), postgres, mysql
+ * added unit tests
+
+**0.5** (2008-05-10)
+====================
+
+ * initial production version
+ * consolidated from code scattered across multiple applications
+ * MD5-Crypt, SHA256-Crypt, SHA512-Crypt support
diff --git a/docs/history/index.rst b/docs/history/index.rst
new file mode 100644
index 0000000..2210562
--- /dev/null
+++ b/docs/history/index.rst
@@ -0,0 +1,22 @@
+.. -*- restructuredtext -*-
+
+===============
+Release History
+===============
+
+.. centered:: This documentation is for the :ref:`1.7.0 Release <whats-new>` of Passlib.
+
+.. rst-class:: float-right
+
+.. seealso::
+
+ The `Roadmap <https://bitbucket.org/ecollins/passlib/wiki/Roadmap>`_
+ for a list of future changes that may impact applications.
+
+.. toctree::
+ :maxdepth: 2
+
+ 1.7
+ 1.6
+ 1.5
+ ancient
diff --git a/docs/index.rst b/docs/index.rst
index 9aa5065..6fa4d31 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -51,13 +51,13 @@ Getting Started
This documentation is organized into two main parts:
a narrative walkthrough of Passlib, and a top-down API reference.
-:doc:`narrative`
+:doc:`narr/index`
New users in particular will want to visit the walkthrough, as it provides
introductory documentation including installation requirements,
an overview of what passlib provides, and a guide for getting started quickly.
-:doc:`reference`
+:doc:`lib/index`
The API reference contains a top-down reference of the :mod:`!passlib` package.
@@ -65,7 +65,7 @@ a narrative walkthrough of Passlib, and a top-down API reference.
This section contains additional things that don't
fit anywhere else, including an :doc:`FAQ <faq>` and a complete
- :doc:`changelog <history>`.
+ :doc:`changelog <history/index>`.
Online Resources
================
@@ -75,7 +75,7 @@ Online Resources
:column-alignment: lr
=================== ===================================================
- Latest Docs: `<http://packages.python.org/passlib>`_
+ Latest Docs: `<https://passlib.readthedocs.io>`_
Project Home: `<https://bitbucket.org/ecollins/passlib>`_
News & Discussion: `<http://groups.google.com/group/passlib-users>`_
Downloads @ PyPI: `<https://pypi.python.org/pypi/passlib>`_
diff --git a/docs/install.rst b/docs/install.rst
index 6637b35..6ee3d7f 100644
--- a/docs/install.rst
+++ b/docs/install.rst
@@ -68,7 +68,7 @@ Optional Libraries
* `SCrypt <https://pypi.python.org/pypi/scrypt>`_ (>= 0.6)
- If installed, this will be used to provider support for the :class:`~passlib.hash.scrypt`
+ If installed, this will be used to provide support for the :class:`~passlib.hash.scrypt`
hash algorithm. If not installed, a MUCH slower builtin reference implementation will be used.
.. versionchanged:: 1.7
@@ -82,6 +82,14 @@ To install from PyPi using :command:`pip`::
pip install passlib
+..
+ As noted above, you can ensure you have feature-specific extras installed
+ via any of::
+
+ pip install passlib[argon2]
+ pip install passlib[bcrypt]
+ pip install passlib[totp]
+
To install from the source using :command:`setup.py`::
python setup.py install
@@ -117,7 +125,7 @@ Tests may also be run via ``setup.py test`` or the included ``tox.ini`` file.
Building the Documentation
==========================
The latest copy of this documentation should always be available
-online at `<http://packages.python.org/passlib>`_.
+online at `<https://passlib.readthedocs.io>`_.
If you wish to generate your own copy of the documentation,
you will need to:
diff --git a/docs/lib/index.rst b/docs/lib/index.rst
new file mode 100644
index 0000000..14f6d7d
--- /dev/null
+++ b/docs/lib/index.rst
@@ -0,0 +1,55 @@
+=============
+API Reference
+=============
+
+The reference section contains documentation of Passlib's public API.
+These chapters are focused on providing detailed reference of the individual
+functions and classes; they will generally be cross-linked to any related walkthrough
+documentation (which tries to provide a higher-level synthetic view).
+
+.. rst-class:: float-right without-title
+
+.. note::
+
+ **Primary modules:**
+
+ The primary modules that will be of interest are:
+
+ * :mod:`passlib.hash`
+ * :mod:`passlib.context`
+ * :mod:`passlib.totp`
+ * :mod:`passlib.exc`
+
+.. rst-class:: float-right without-title clear-right
+
+.. caution::
+
+ **Internal modules:**
+
+ The following modules are mainly used internally,
+ may change structure between releases,
+ and are documented mainly for completeness:
+
+ * :mod:`passlib.crypto`
+ * :mod:`passlib.registry`
+ * :mod:`passlib.utils`
+
+**Alphabetical module list:**
+
+.. toctree::
+ :titlesonly:
+ :maxdepth: 1
+
+ passlib.apache
+ passlib.apps
+ passlib.context
+ passlib.crypto
+ passlib.exc
+ passlib.ext.django
+ passlib.hash
+ passlib.hosts
+ passlib.ifc
+ passlib.pwd
+ passlib.registry
+ passlib.totp
+ passlib.utils
diff --git a/docs/lib/passlib.apps.rst b/docs/lib/passlib.apps.rst
index ca22050..e89b804 100644
--- a/docs/lib/passlib.apps.rst
+++ b/docs/lib/passlib.apps.rst
@@ -7,7 +7,7 @@
.. _predefined-context-example:
-This module contains a number of preconfigured :ref:`CryptContext <context-overview>` instances
+This module contains a number of preconfigured :ref:`CryptContext <context-reference>` instances
that are provided by Passlib for easily handling the hash formats used by various applications.
.. rst-class:: html-toggle
@@ -252,4 +252,4 @@ Custom Applications
.. seealso::
- The :doc:`/new_app_quickstart` for additional details.
+ The :doc:`/narr/quickstart` for additional details.
diff --git a/docs/lib/passlib.context.rst b/docs/lib/passlib.context.rst
index 262ef46..2c95a74 100644
--- a/docs/lib/passlib.context.rst
+++ b/docs/lib/passlib.context.rst
@@ -14,7 +14,7 @@ and helper utilities.
.. seealso::
- * :ref:`CryptContext Overview & Tutorial <context-overview>` --
+ * :ref:`context-tutorial` --
overview of this class and walkthrough of how to use it.
.. rst-class:: emphasize-children toc-always-open
diff --git a/docs/lib/passlib.crypto.digest.rst b/docs/lib/passlib.crypto.digest.rst
index 942f11d..91e2a4d 100644
--- a/docs/lib/passlib.crypto.digest.rst
+++ b/docs/lib/passlib.crypto.digest.rst
@@ -16,7 +16,7 @@ Hash Functions
.. autofunction:: norm_hash_name
.. autofunction:: lookup_hash
-.. autoclass:: HashInfo()
+.. rst-class:: float-center
.. note::
@@ -24,6 +24,8 @@ Hash Functions
as well as offered through :func:`hashlib.new`.
It will also fallback to passlib's builtin MD4 implementation if one is not natively available.
+.. autoclass:: HashInfo()
+
..
HMAC Functions
==============
diff --git a/docs/lib/passlib.exc.rst b/docs/lib/passlib.exc.rst
index 4b36a2b..10647a3 100644
--- a/docs/lib/passlib.exc.rst
+++ b/docs/lib/passlib.exc.rst
@@ -21,6 +21,8 @@ Exceptions
.. autoexception:: PasslibSecurityError
+.. autoexception:: UnknownHashError
+
TOTP Exceptions
---------------
.. autoexception:: TokenError
diff --git a/docs/lib/passlib.ext.django.rst b/docs/lib/passlib.ext.django.rst
index b05c0e7..8fd4e83 100644
--- a/docs/lib/passlib.ext.django.rst
+++ b/docs/lib/passlib.ext.django.rst
@@ -14,7 +14,7 @@
This module contains a `Django <http://www.djangoproject.com>`_ plugin which
overrides all of Django's password hashing functions, replacing them
-with wrappers around a Passlib :ref:`CryptContext <context-overview>` object
+with wrappers around a Passlib :ref:`CryptContext <context-reference>` object
whose configuration is controlled from Django's ``settings``.
While this extension's utility is diminished with the advent
of Django 1.4's *hashers* framework, this plugin still has a number
diff --git a/docs/lib/passlib.hash.apr_md5_crypt.rst b/docs/lib/passlib.hash.apr_md5_crypt.rst
index 6c8a489..4ce222c 100644
--- a/docs/lib/passlib.hash.apr_md5_crypt.rst
+++ b/docs/lib/passlib.hash.apr_md5_crypt.rst
@@ -4,10 +4,7 @@
:class:`passlib.hash.apr_md5_crypt` - Apache's MD5-Crypt variant
======================================================================
-.. warning::
-
- As of 2012-6-7, the MD5-Crypt algorithm is "no longer considered safe"
- by its author, who urges migration to newer hash algorithms.
+.. include:: ../_fragments/insecure_hash_warning.rst
.. currentmodule:: passlib.hash
diff --git a/docs/lib/passlib.hash.bigcrypt.rst b/docs/lib/passlib.hash.bigcrypt.rst
index a958aa5..fa9542b 100644
--- a/docs/lib/passlib.hash.bigcrypt.rst
+++ b/docs/lib/passlib.hash.bigcrypt.rst
@@ -2,9 +2,7 @@
:class:`passlib.hash.bigcrypt` - BigCrypt
=======================================================================
-.. warning::
-
- This algorithm is dangerously weak, and should not be used if at all possible.
+.. include:: ../_fragments/trivial_hash_warning.rst
.. currentmodule:: passlib.hash
diff --git a/docs/lib/passlib.hash.bsdi_crypt.rst b/docs/lib/passlib.hash.bsdi_crypt.rst
index 63d4b0e..137a7c6 100644
--- a/docs/lib/passlib.hash.bsdi_crypt.rst
+++ b/docs/lib/passlib.hash.bsdi_crypt.rst
@@ -2,11 +2,9 @@
:class:`passlib.hash.bsdi_crypt` - BSDi Crypt
=================================================================================
-.. currentmodule:: passlib.hash
-
-.. note::
+.. include:: ../_fragments/insecure_hash_warning.rst
- This algorithm is weak by modern standards, and should not be used in new applications.
+.. currentmodule:: passlib.hash
This algorithm was developed by BSDi for their BSD/OS distribution.
It's based on :class:`~passlib.hash.des_crypt`, and contains a larger
diff --git a/docs/lib/passlib.hash.cisco_asa.rst b/docs/lib/passlib.hash.cisco_asa.rst
index eb0b643..3b9e757 100644
--- a/docs/lib/passlib.hash.cisco_asa.rst
+++ b/docs/lib/passlib.hash.cisco_asa.rst
@@ -4,11 +4,15 @@
:class:`passlib.hash.cisco_asa` - Cisco ASA hash
==================================================================
+.. include:: ../_fragments/insecure_hash_warning.rst
+
.. currentmodule:: passlib.hash
.. versionadded:: 1.7
+The :class:`!cisco_asa` handler provides support for the 2005 revision of the older :class:`!cisco_pix` hash.
+The usage, functionality, and format is the same as for :class:`!cisco_pix`,
+
.. seealso::
- The :class:`!cisco_asa` handler provides support for the 2005 revision of the older :class:`!cisco_pix` hash.
- The usage, functionality, and format is the same. It's documented on the :doc:`cisco_pix page <passlib.hash.cisco_pix>`.
+ :doc:`cisco_pix <passlib.hash.cisco_pix>` documentation page.
diff --git a/docs/lib/passlib.hash.cisco_pix.rst b/docs/lib/passlib.hash.cisco_pix.rst
index ab11a5f..9ad9fdd 100644
--- a/docs/lib/passlib.hash.cisco_pix.rst
+++ b/docs/lib/passlib.hash.cisco_pix.rst
@@ -4,12 +4,9 @@
:class:`passlib.hash.cisco_pix` - Cisco PIX hash
==================================================================
-.. versionadded:: 1.6
-
-.. warning::
+.. include:: ../_fragments/insecure_hash_warning.rst
- These hashes are not secure, and should not be used for any purposes
- besides manipulating existing hashes.
+.. versionadded:: 1.6
.. todo::
diff --git a/docs/lib/passlib.hash.cisco_type7.rst b/docs/lib/passlib.hash.cisco_type7.rst
index a6efb16..6512582 100644
--- a/docs/lib/passlib.hash.cisco_type7.rst
+++ b/docs/lib/passlib.hash.cisco_type7.rst
@@ -4,13 +4,13 @@
:class:`passlib.hash.cisco_type7` - Cisco "Type 7" hash
==================================================================
-.. versionadded:: 1.6
-
-.. warning::
+.. danger::
This is not a hash, this is a reversible plaintext encoding.
**This format can be trivially decoded**.
+.. versionadded:: 1.6
+
.. currentmodule:: passlib.hash
This class implements the "Type 7" password encoding used Cisco IOS.
diff --git a/docs/lib/passlib.hash.crypt16.rst b/docs/lib/passlib.hash.crypt16.rst
index 101d9dd..187c320 100644
--- a/docs/lib/passlib.hash.crypt16.rst
+++ b/docs/lib/passlib.hash.crypt16.rst
@@ -2,9 +2,7 @@
:class:`passlib.hash.crypt16` - Crypt16
=======================================================================
-.. warning::
-
- This algorithm is dangerously weak, and should not be used if at all possible.
+.. include:: ../_fragments/trivial_hash_warning.rst
.. currentmodule:: passlib.hash
diff --git a/docs/lib/passlib.hash.des_crypt.rst b/docs/lib/passlib.hash.des_crypt.rst
index 373259f..dfd61f5 100644
--- a/docs/lib/passlib.hash.des_crypt.rst
+++ b/docs/lib/passlib.hash.des_crypt.rst
@@ -2,10 +2,7 @@
:class:`passlib.hash.des_crypt` - DES Crypt
=======================================================================
-.. warning::
-
- This algorithm is extremely weak by modern standards,
- and should not be used if possible.
+.. include:: ../_fragments/trivial_hash_warning.rst
.. currentmodule:: passlib.hash
diff --git a/docs/lib/passlib.hash.hex_digests.rst b/docs/lib/passlib.hash.hex_digests.rst
index 0f8efc0..8e66b87 100644
--- a/docs/lib/passlib.hash.hex_digests.rst
+++ b/docs/lib/passlib.hash.hex_digests.rst
@@ -2,7 +2,7 @@
:samp:`passlib.hash.hex_{digest}` - Generic Hexadecimal Digests
===============================================================
-.. warning::
+.. danger::
Using a single round of any cryptographic hash
(especially without a salt) is so insecure
diff --git a/docs/lib/passlib.hash.lmhash.rst b/docs/lib/passlib.hash.lmhash.rst
index 0a9e627..26a4164 100644
--- a/docs/lib/passlib.hash.lmhash.rst
+++ b/docs/lib/passlib.hash.lmhash.rst
@@ -4,13 +4,9 @@
:class:`passlib.hash.lmhash` - LanManager Hash
==================================================================
-.. versionadded:: 1.6
-
-.. warning::
+.. include:: ../_fragments/insecure_hash_warning.rst
- This scheme has been deprecated since Windows NT, and is notoriously weak.
- It should be used for compatibility with existing systems;
- **do not use** in new code.
+.. versionadded:: 1.6
.. currentmodule:: passlib.hash
@@ -122,9 +118,13 @@ the handling of non-ASCII characters.
MS Windows implementation.
Thus if an application wishes to provide support for non-ASCII passwords,
- it must decide which encoding to use. Passlib uses ``cp437`` as a
- default, but this may need to be overridden via
- ``lmhash.hash(secret, encoding="some-other-codec")``.
+ it must decide which encoding to use.
+
+ Passlib uses ``cp437`` as it's default encoding for unicode strings.
+ However, if your database used a different encoding, you will need to either
+ first encode the passwords into bytes, or override the default encoding
+ via ``lmhash.hash(secret, encoding="some-other-codec")``
+
All known encodings are ``us-ascii``-compatible, so for ASCII passwords,
the default should be sufficient.
diff --git a/docs/lib/passlib.hash.md5_crypt.rst b/docs/lib/passlib.hash.md5_crypt.rst
index 528367e..3251f12 100644
--- a/docs/lib/passlib.hash.md5_crypt.rst
+++ b/docs/lib/passlib.hash.md5_crypt.rst
@@ -4,14 +4,8 @@
:class:`passlib.hash.md5_crypt` - MD5 Crypt
==================================================================
-.. warning::
-
- As of 2012-6-7, this algorithm is "no longer considered safe"
- by its author [#phk]_, citing the increased
- speed of the MD5 hash on modern hardware, and MD5-Crypt's
- lack of a variable time-cost parameter. See Passlib's
- :ref:`recommended hashes <recommended-hashes>` for a replacement.
-
+.. include:: ../_fragments/insecure_hash_warning.rst
+
.. currentmodule:: passlib.hash
This algorithm was developed for FreeBSD in 1994 by Poul-Henning Kamp,
diff --git a/docs/lib/passlib.hash.msdcc.rst b/docs/lib/passlib.hash.msdcc.rst
index 6c72aff..acfd87f 100644
--- a/docs/lib/passlib.hash.msdcc.rst
+++ b/docs/lib/passlib.hash.msdcc.rst
@@ -7,12 +7,9 @@
:class:`passlib.hash.msdcc` - Windows' Domain Cached Credentials
======================================================================
-.. versionadded:: 1.6
-
-.. warning::
+.. include:: ../_fragments/insecure_hash_warning.rst
- This hash is not very secure, and should mainly be used to verify
- existing cached credentials.
+.. versionadded:: 1.6
.. currentmodule:: passlib.hash
diff --git a/docs/lib/passlib.hash.mssql2000.rst b/docs/lib/passlib.hash.mssql2000.rst
index 416bce6..481008c 100644
--- a/docs/lib/passlib.hash.mssql2000.rst
+++ b/docs/lib/passlib.hash.mssql2000.rst
@@ -2,12 +2,9 @@
:class:`passlib.hash.mssql2000` - MS SQL 2000 password hash
==================================================================
-.. versionadded:: 1.6
-
-.. warning::
+.. include:: ../_fragments/insecure_hash_warning.rst
- This hash is not very secure, and should not be used for any purposes
- besides manipulating existing MSSQL 2000 password hashes.
+.. versionadded:: 1.6
.. currentmodule:: passlib.hash
diff --git a/docs/lib/passlib.hash.mssql2005.rst b/docs/lib/passlib.hash.mssql2005.rst
index 3b997da..bb6b0ec 100644
--- a/docs/lib/passlib.hash.mssql2005.rst
+++ b/docs/lib/passlib.hash.mssql2005.rst
@@ -2,12 +2,9 @@
:class:`passlib.hash.mssql2005` - MS SQL 2005 password hash
==================================================================
-.. versionadded:: 1.6
-
-.. warning::
+.. include:: ../_fragments/insecure_hash_warning.rst
- This hash is not very secure, and should not be used for any purposes
- besides manipulating existing MSSQL 2005 password hashes.
+.. versionadded:: 1.6
.. currentmodule:: passlib.hash
diff --git a/docs/lib/passlib.hash.mysql323.rst b/docs/lib/passlib.hash.mysql323.rst
index 207602b..eab3e3e 100644
--- a/docs/lib/passlib.hash.mysql323.rst
+++ b/docs/lib/passlib.hash.mysql323.rst
@@ -4,13 +4,9 @@
:class:`passlib.hash.mysql323` - MySQL 3.2.3 password hash
========================================================================
-.. currentmodule:: passlib.hash
-
-.. warning::
+.. include:: ../_fragments/insecure_hash_warning.rst
- This algorithm is extremely weak, and should not be used
- for any purposes besides manipulating existing Mysql 3.2.3-4.0
- password hashes.
+.. currentmodule:: passlib.hash
This class implements the first of MySQL's password hash functions,
used to store its user account passwords. Introduced in MySQL 3.2.3
diff --git a/docs/lib/passlib.hash.mysql41.rst b/docs/lib/passlib.hash.mysql41.rst
index b38d481..716181f 100644
--- a/docs/lib/passlib.hash.mysql41.rst
+++ b/docs/lib/passlib.hash.mysql41.rst
@@ -4,13 +4,9 @@
:class:`passlib.hash.mysql41` - MySQL 4.1 password hash
=====================================================================
-.. currentmodule:: passlib.hash
-
-.. warning::
+.. include:: ../_fragments/insecure_hash_warning.rst
- This algorithm is extremely weak, and should not be used
- for any purposes besides manipulating existing Mysql 4.1+
- password hashes.
+.. currentmodule:: passlib.hash
This class implements the second of MySQL's password hash functions,
used to store its user account passwords. Introduced in MySQL 4.1.1
diff --git a/docs/lib/passlib.hash.nthash.rst b/docs/lib/passlib.hash.nthash.rst
index c93dff4..92c934e 100644
--- a/docs/lib/passlib.hash.nthash.rst
+++ b/docs/lib/passlib.hash.nthash.rst
@@ -4,14 +4,9 @@
:class:`passlib.hash.nthash` - Windows' NT-HASH
==================================================================
-.. versionadded:: 1.6
-
-.. warning::
+.. include:: ../_fragments/trivial_hash_warning.rst
- This scheme is very weak, the MD4 digest
- it is based on has been severely compromised for many years.
- It should be used for compatibility with existing systems;
- **do not use** in new code.
+.. versionadded:: 1.6
.. currentmodule:: passlib.hash
diff --git a/docs/lib/passlib.hash.oracle10.rst b/docs/lib/passlib.hash.oracle10.rst
index d2c6524..3d697c2 100644
--- a/docs/lib/passlib.hash.oracle10.rst
+++ b/docs/lib/passlib.hash.oracle10.rst
@@ -2,12 +2,9 @@
:class:`passlib.hash.oracle10` - Oracle 10g password hash
==================================================================
-.. currentmodule:: passlib.hash
-
-.. warning::
+.. include:: ../_fragments/trivial_hash_warning.rst
- This hash is not secure, and should not be used for any purposes
- besides manipulating existing Oracle 10 password hashes.
+.. currentmodule:: passlib.hash
This class implements the hash algorithm used by the Oracle Database up to
version 10g Rel.2. It was superseded by a newer algorithm in :class:`Oracle 11 <passlib.hash.oracle11>`.
diff --git a/docs/lib/passlib.hash.postgres_md5.rst b/docs/lib/passlib.hash.postgres_md5.rst
index e14dc18..4627eb7 100644
--- a/docs/lib/passlib.hash.postgres_md5.rst
+++ b/docs/lib/passlib.hash.postgres_md5.rst
@@ -4,10 +4,7 @@
:class:`passlib.hash.postgres_md5` - PostgreSQL MD5 password hash
==================================================================
-.. warning::
-
- This hash is not secure, and should not be used for any purposes
- besides manipulating existing PostgreSQL password hashes.
+.. include:: ../_fragments/insecure_hash_warning.rst
.. currentmodule:: passlib.hash
diff --git a/docs/lib/passlib.hash.rst b/docs/lib/passlib.hash.rst
index 03a28b1..f5a728c 100644
--- a/docs/lib/passlib.hash.rst
+++ b/docs/lib/passlib.hash.rst
@@ -9,11 +9,13 @@ Overview
========
The :mod:`!passlib.hash` module contains all the password hash algorithms built into Passlib.
While each hash has its own options and output format,
-they all inherit from the :mod:`passlib.ifc`.\ :class:`!PasswordHash` API.
+they all inherit from the :mod:`~passlib.ifc.PasswordHash` base interface.
The following pages describe each hash in detail,
including its format, underlying algorithm, and known security issues.
-.. warning::
+.. rst-class:: float-center
+
+.. danger::
**Many of the hash algorithms listed below are *NOT* secure.**
@@ -21,61 +23,14 @@ including its format, underlying algorithm, and known security issues.
support dealing with legacy data and systems.
If you're looking to choose a hash algorithm for a new application,
- see the :doc:`Quickstart Guide </new_app_quickstart>` instead of picking
+ see the :doc:`Quickstart Guide </narr/quickstart>` instead of picking
one from this list.
-.. rst-class:: html-toggle
-
-Usage
------
-All of the hashes in this module can be used in two ways:
-
-1. They can be imported from :mod:`!passlib.hash` and used directly,
- as in the following example with the :class:`md5_crypt` hash::
-
- >>> # import the desired hash
- >>> from passlib.hash import md5_crypt
-
- >>> # hash the password - hash() takes care of salt generation, unicode encoding, etc.
- >>> hash = md5_crypt.hash("password")
- >>> hash
- '$1$IU54yC7Y$nI1wF8ltcRvaRHwMIjiJq1'
-
- >>> # verify a password against an existing hash:
- >>> md5_crypt.verify("password", hash)
- True
-
-2. Alternately, when working with multiple algorithms at once, it is frequently useful
- to construct a :ref:`CryptContext <context-overview>` object instead;
- and reference the hashes by name only. For example, the following
- code creates a :class:`!CryptContext` object which recognizes both
- the :class:`md5_crypt` and :class:`des_crypt` hash algorithms::
-
- >>> # import and create the context object
- >>> from passlib.context import CryptContext
- >>> pwd_context = CryptContext(schemes=["md5_crypt", "des_crypt"])
-
- >>> # hash two different passwords (context objects used the first scheme as the default)
- >>> hash1 = pwd_context.hash("password")
- >>> hash1
- '$1$2y72Yi12$o6Yu2OyjN.9FiK.9HJ7i5.'
- >>> hash2 = pwd_context.hash("letmein", scheme="des_crypt")
- >>> hash2
- '0WMdk/ven8bok'
-
- >>> # the context object takes care of figuring out which hash belongs to which algorithm.
- >>> pwd_context.verify("password", hash1)
- True
- >>> pwd_context.verify("letmein", hash1)
- False
- >>> pwd_context.verify("letmein", hash2)
- True
+.. rst-class:: float-center
.. seealso::
- For additional details and usage examples, see the
- :doc:`PasswordHash </password_hash_api>` and :doc:`CryptContext </lib/passlib.context>`
- reference.
+ :ref:`hash-tutorial` -- for general usage examples
.. _mcf-hashes:
diff --git a/docs/lib/passlib.hash.scrypt.rst b/docs/lib/passlib.hash.scrypt.rst
index 29f491a..6c2c061 100644
--- a/docs/lib/passlib.hash.scrypt.rst
+++ b/docs/lib/passlib.hash.scrypt.rst
@@ -14,8 +14,10 @@ as the of a new generation of "memory hard" functions.
Be careful when using this algorithm, as the memory and CPU requirements
needed to achieve adequate security are generally higher than acceptable for heavily used
- production systems [#scrypt-cost]_: unlike many password hashes, increasing
- the rounds value of scrypt will increase the *memory* required, as well as the time.
+ production systems [#scrypt-cost]_. This is because (unlike many password hashes), increasing
+ the rounds value of scrypt will increase the *memory* required as well as the time.
+
+ Unless you know what you're doing, **You probably want** :doc:`argon2 <passlib.hash.argon2>` **instead.**
This class can be used directly as follows::
diff --git a/docs/lib/passlib.hosts.rst b/docs/lib/passlib.hosts.rst
index 3a0a02e..d72fef0 100644
--- a/docs/lib/passlib.hosts.rst
+++ b/docs/lib/passlib.hosts.rst
@@ -5,7 +5,7 @@
.. module:: passlib.hosts
:synopsis: encrypting & verifying operating system passwords
-This module provides some preconfigured :ref:`CryptContext <context-overview>`
+This module provides some preconfigured :ref:`CryptContext <context-reference>`
instances for encrypting & verifying password hashes tied to user accounts of various operating systems.
While (most) of the objects are available cross-platform,
their use is oriented primarily towards Linux and BSD variants.
diff --git a/docs/password_hash_api.rst b/docs/lib/passlib.ifc.rst
index a2daf45..0cc99f0 100644
--- a/docs/password_hash_api.rst
+++ b/docs/lib/passlib.ifc.rst
@@ -5,134 +5,61 @@
.. module:: passlib.ifc
:synopsis: abstract interfaces used by Passlib
-.. _password-hash-api:
-
=============================================
:mod:`passlib.ifc` -- Password Hash Interface
=============================================
+.. _password-hash-api:
+
Overview
========
-While the exact options and behavior will vary between algorithms,
-all of the hashes provided by Passlib use the same interface,
-defined by the following abstract base class:
+This module provides the :class:`!PasswordHash` abstract base class.
+This class defines the common methods and attributes present
+on all the hashes importable from the :mod:`passlib.hash` module.
+Additionally, the :class:`passlib.context.CryptContext` class is deliberately
+designed to parallel many of this interface's methods.
+
+.. rst-class:: float-center
+.. seealso::
+
+ :ref:`hash-tutorial` -- Overview of this interface and how to use it.
+
+PasswordHash API
+================
.. class:: PasswordHash()
- This class provides an abstract interface for
- an arbitrary password hashing algorithm.
- While it offers a number of methods and attributes,
- but most applications will only need the two primary methods:
+ This class provides an abstract interface for an arbitrary password hasher.
+
+ Applications will generally not construct instances directly --
+ most of the operations are performed via classmethods, allowing
+ instances of a given class to be an internal detail used to implement
+ the various operations.
+
+ While :class:`!PasswordHash` offers a number of methods and attributes,
+ most applications will only need the two primary methods:
- * :meth:`~PasswordHash.hash` - generate new salt, return hash of password.
- * :meth:`~PasswordHash.verify` - verify password against existing hash.
+ * :meth:`PasswordHash.hash` - generate new salt, return hash of password.
+ * :meth:`PasswordHash.verify` - verify password against existing hash.
- One additional support method is provided:
+ Two additional support methods are also provided:
- * :meth:`~PasswordHash.identify` - check if hash belongs to this algorithm.
+ * :meth:`PasswordHash.using` - create subclass with customized configuration.
+ * :meth:`PasswordHash.identify` - check if hash belongs to this algorithm.
Each hash algorithm also provides a number of :ref:`informational attributes <informational-attributes>`,
allowing programmatic inspection of its options and parameter limits.
-.. _password-hash-examples:
-
-Usage Examples
-==============
-The following code shows how to use the primary
-methods of the :class:`~passlib.ifc.PasswordHash` interface --
-:meth:`~PasswordHash.hash` and :meth:`~PasswordHash.verify` --
-using the :class:`~passlib.hash.pbkdf2_sha256` hash as an example::
-
- >>> # import the handler class
- >>> from passlib.hash import pbkdf2_sha256
-
- >>> # hash a password using the default settings:
- >>> hash = pbkdf2_sha256.hash("password")
- >>> hash
- '$pbkdf2-sha256$29000$791b633vXau19h4jxPj/Pw$qyzGzFapr0oDhS60GR8Ss40Y/wwd8AcaJoJ5/KKnnN8'
-
- >>> # note that each call to hash() generates a new salt,
- >>> # and thus the contents of the hash will differ, despite using the same password:
- >>> pbkdf2_sha256.hash("password")
- '$pbkdf2-sha256$29000$njNmDCGEUIoRwvi/1/ofQw$nYU.7v.fvG9UyT.7sTMbWSG98KSm/Tr4rS9Ob5UkYPw
-
- >>> # if the hash supports a variable number of iterations (which pbkdf2_sha256 does),
- >>> # you can override the default using the replace() method and the 'rounds' keyword:
- >>> pbkdf2_sha256.using(rounds=12345).hash("password")
- '$pbkdf2-sha256$12345$QwjBmJPSOsf4HyNE6L239g$8m1pnP69EYeOiKKb5sNSiYw9M8pJMyeW.CSm0KKO.GI'
- ^^^^^
-
- >>> # on the other end of things, the verify() method takes care of
- >>> # checking if a password matches an existing hash string:
- >>> pbkdf2_sha256.verify("password", hash)
- True
- >>> pbkdf2_sha256.verify("letmeinplz", hash)
- False
-
-.. note::
-
- Whether a hash supports a particular configuration keyword (such as ``rounds``)
- can be determined from its documentation page; but also programmatically from
- its :attr:`~PasswordHash.setting_kwds` attribute.
-
-That concludes the most basic example, but there are a few more
-common use-cases, such as how to use the :meth:`~PasswordHash.identify` method::
-
- >>> # attempting to call verify() with another algorithm's hash will result in a ValueError:
- >>> from passlib.hash import pbkdf2_sha256, md5_crypt
- >>> other_hash = md5_crypt.hash("password")
- >>> pbkdf2_sha256.verify("password", other_hash)
- Traceback (most recent call last):
- <traceback omitted>
- ValueError: not a valid pbkdf2_sha256 hash
-
- >>> # this can be prevented by using the identify method,
- >>> # determines whether a hash belongs to a given algorithm:
- >>> hash = pbkdf2_sha256.hash("password")
- >>> pbkdf2_sha256.identify(hash)
- True
- >>> pbkdf2_sha256.identify(other_hash)
- False
-
-While the initial :meth:`~PasswordHash.hash` example works for most hashes,
-a small number of algorithms require you provide external data
-(such as a username) every time a hash is calculated.
-An example of this is the :class:`~passlib.hash.oracle10` algorithm::
-
- >>> # for oracle10, encrypt requires a username:
- >>> from passlib.hash import oracle10
- >>> hash = oracle10.hash("secret", user="admin")
- 'B858CE295C95193F'
-
- >>> # the difference between this and something like the rounds setting (above)
- >>> # is that oracle10 also requires the username when verifying a hash:
- >>> oracle10.verify("secret", hash, user="admin")
- True
-
- >>> # if either the username OR password is wrong, verify() will fail:
- >>> oracle10.verify("secret", hash, user="wronguser")
- False
- >>> oracle10.verify("wrongpassword", hash, user="admin")
- False
-
- >>> # forgetting to include the username when it's required will cause a TypeError:
- >>> hash = oracle10.hash("password")
- Traceback (most recent call last):
- <traceback omitted>
- TypeError: user must be unicode or bytes, not None
-
-.. note::
-
- Whether a hash requires external parameters (such as ``user``)
- can be determined from its documentation page; but also programmatically from
- its :attr:`~PasswordHash.context_kwds` attribute.
+.. seealso::
+
+ :ref:`hash-tutorial` -- Overview of this interface and how to use it.
.. _primary-methods:
-Primary Methods
-===============
+Hashing & Verification Methods
+==============================
Most applications will only need to use two methods:
-:meth:`~PasswordHash.hash` to generate new hashes, and :meth:`~PasswordHash.verify`
+:meth:`PasswordHash.hash` to generate new hashes, and :meth:`PasswordHash.verify`
to check passwords against existing hashes.
These methods provide an easy interface for working with a password hash,
and abstract away details such as salt generation, hash normalization,
@@ -154,12 +81,12 @@ and hash comparison.
All additional keywords are algorithm-specific, and will be listed
in that hash's documentation; though many of the more common keywords
- are listed under :attr:`~PasswordHash.setting_kwds`
- and :attr:`~PasswordHash.context_kwds`.
+ are listed under :attr:`PasswordHash.setting_kwds`
+ and :attr:`PasswordHash.context_kwds`.
.. deprecated:: 1.7
- Passing :attr:`~PasswordHash.setting_kwds` such as ``rounds`` and ``salt_size``
+ Passing :attr:`PasswordHash.setting_kwds` such as ``rounds`` and ``salt_size``
directly into the :meth:`hash` method is deprecated. Callers should instead
use ``handler.using(**settings).hash(secret)``. Support for the old method
is is tentatively scheduled for removal in Passlib 2.0.
@@ -203,7 +130,7 @@ and hash comparison.
.. classmethod:: PasswordHash.encrypt(secret, \*\*kwds)
- Legacy alias for :meth:`hash`.
+ Legacy alias for :meth:`PasswordHash.hash`.
.. deprecated:: 1.7
@@ -225,7 +152,7 @@ and hash comparison.
:type secret: unicode or bytes
:param hash:
A string containing the hash to check against,
- such as returned by :meth:`~hash`.
+ such as returned by :meth:`PasswordHash.hash`.
Hashes may be specified as :class:`!unicode` or
``ascii``-encoded :class:`!bytes`.
@@ -236,12 +163,12 @@ and hash comparison.
The ones that do typically require external contextual information
in order to calculate the digest. For these hashes,
the values must match the ones passed to the original
- :meth:`~PasswordHash.hash` call when the hash was generated,
+ :meth:`PasswordHash.hash` call when the hash was generated,
or the password will not verify.
These additional keywords are algorithm-specific, and will be listed
in that hash's documentation; though the more common keywords
- are listed under :attr:`~PasswordHash.context_kwds`.
+ are listed under :attr:`PasswordHash.context_kwds`.
Examples of common keywords include ``user``.
:returns:
@@ -255,8 +182,8 @@ and hash comparison.
:raises ValueError:
* if ``hash`` does not match this algorithm's format.
* if the ``secret`` contains forbidden characters (see
- :meth:`~PasswordHash.hash`).
- * if a configuration/salt string generated by :meth:`~PasswordHash.genconfig`
+ :meth:`PasswordHash.hash`).
+ * if a configuration/salt string generated by :meth:`PasswordHash.genconfig`
is passed in as the value for ``hash`` (these strings look
similar to a full hash, but typically lack the digest portion
needed to verify a password).
@@ -266,52 +193,9 @@ and hash comparison.
instead of a properly-formed hash; previous releases were inconsistent
in their handling of these two border cases.
-.. classmethod:: PasswordHash.using(relaxed=False, \*\*settings)
-
- This method takes in a set of algorithm-specific settings,
- and returns a new handler object which uses the specified default settings instead.
-
- :param \*\*settings:
-
- All keywords are algorithm-specific, and will be listed
- in that hash's documentation; though many of the more common keywords
- are listed under :attr:`~PasswordHash.setting_kwds`.
- Examples of common keywords include ``rounds`` and ``salt_size``.
-
- :returns:
- A new object which adheres to :class:`!PasswordHash` api.
-
- :raises ValueError:
-
- * If a keywords's value is invalid (e.g. if a ``salt`` string
- is too small, or a ``rounds`` value is out of range).
-
- :raises TypeError:
-
- * if a ``kwd`` argument has an incorrect type.
-
- .. versionadded:: 1.7
-
-.. _hash-unicode-behavior:
-
-.. note::
-
- Regarding unicode passwords & non-ASCII characters:
-
- For the majority of hash algorithms and use-cases, passwords should
- be provided as either :class:`!unicode` or ``utf-8``-encoded :class:`!bytes`.
- There are only two major exceptions:
-
- * Some systems have legacy hashes that were generated using a different
- character encoding. In this case, all :class:`!unicode` passwords
- should be encoded using the correct encoding before they are hashed;
- otherwise non-ASCII passwords may not :meth:`!verify` successfully.
+.. seealso::
- * For historical reasons, :class:`~passlib.hash.lmhash` uses ``cp437``
- as its default encoding. It will handle :class:`!unicode` correctly;
- but non-ASCII passwords provided as :class:`!bytes` must either be encoded
- using ``"cp437"``, or :class:`!lmhash`'s ``encoding`` keyword must
- be set to indicate which encoding was used.
+ * :ref:`hash-verifying` tutorial for a usage example
.. _crypt-methods:
@@ -319,7 +203,7 @@ and hash comparison.
Crypt Methods
=============
-Taken together, the :meth:`~PasswordHash.genconfig` and :meth:`~PasswordHash.genhash`
+Taken together, the :meth:`PasswordHash.genconfig` and :meth:`PasswordHash.genhash`
are two tightly-coupled methods that mimic the standard Unix
"crypt" interface. The first method generates salt / configuration
strings from a set of settings, and the second hashes the password
@@ -327,7 +211,7 @@ using the provided configuration string.
.. seealso::
- Most applications will find :meth:`~PasswordHash.hash` much more useful,
+ Most applications will find :meth:`PasswordHash.hash` much more useful,
as it combines the functionality of these two methods into one.
.. classmethod:: PasswordHash.genconfig(\*\*setting_kwds)
@@ -343,15 +227,15 @@ using the provided configuration string.
Returns a configuration string encoding settings for hash generation.
- This function takes in all the same :attr:`~PasswordHash.setting_kwds`
- as :meth:`~PasswordHash.hash`, fills in suitable defaults,
+ This function takes in all the same :attr:`PasswordHash.setting_kwds`
+ as :meth:`PasswordHash.hash`, fills in suitable defaults,
and encodes the settings into a single "configuration" string,
- suitable passing to :meth:`~PasswordHash.genhash`.
+ suitable passing to :meth:`PasswordHash.genhash`.
:param \*\*kwds:
All additional keywords are algorithm-specific, and will be listed
in that hash's documentation; though many of the more common keywords
- are listed under :attr:`~PasswordHash.setting_kwds`
+ are listed under :attr:`PasswordHash.setting_kwds`
Examples of common keywords include ``salt`` and ``rounds``.
:returns:
@@ -359,7 +243,7 @@ using the provided configuration string.
:raises ValueError, TypeError:
This function raises exceptions for the same
- reasons as :meth:`~PasswordHash.hash`.
+ reasons as :meth:`PasswordHash.hash`.
.. versionchanged:: 1.7
@@ -388,8 +272,8 @@ using the provided configuration string.
:arg config:
configuration string to use when encrypting secret.
this can either be an existing hash that was previously
- returned by :meth:`~PasswordHash.genhash`, or a configuration string
- that was previously created by :meth:`~PasswordHash.genconfig`.
+ returned by :meth:`PasswordHash.genhash`, or a configuration string
+ that was previously created by :meth:`PasswordHash.genconfig`.
.. versionchanged:: 1.7
@@ -402,12 +286,12 @@ using the provided configuration string.
The ones that do typically require external contextual information
in order to calculate the digest. For these hashes,
the values must match the ones passed to the original
- :meth:`~PasswordHash.hash` call when the hash was generated,
+ :meth:`PasswordHash.hash` call when the hash was generated,
or the password will not verify.
These additional keywords are algorithm-specific, and will be listed
in that hash's documentation; though the more common keywords
- are listed under ::attr:`~PasswordHash.context_kwds`.
+ are listed under ::attr:`PasswordHash.context_kwds`.
Examples of common keywords include ``user``.
:returns:
@@ -416,7 +300,7 @@ using the provided configuration string.
:raises ValueError, TypeError:
This function raises exceptions for the same
- reasons as :meth:`~PasswordHash.hash`.
+ reasons as :meth:`PasswordHash.hash`.
.. warning::
@@ -428,9 +312,44 @@ using the provided configuration string.
.. _support-methods:
-Support Methods
-===============
-There is currently one additional support method, :meth:`~PasswordHash.identify`:
+Factory Creation
+================
+One powerful method offered by the :class:`!PasswordHash` class :meth:`PasswordHash.using`.
+This method allows you to quickly create subclasses of a specific hash,
+providing it with preconfigured defaults specific to your application:
+
+.. classmethod:: PasswordHash.using(relaxed=False, \*\*settings)
+
+ This method takes in a set of algorithm-specific settings,
+ and returns a new handler object which uses the specified default settings instead.
+
+ :param \*\*settings:
+
+ All keywords are algorithm-specific, and will be listed
+ in that hash's documentation; though many of the more common keywords
+ are listed under :attr:`PasswordHash.setting_kwds`.
+ Examples of common keywords include ``rounds`` and ``salt_size``.
+
+ :returns:
+ A new object which adheres to :class:`!PasswordHash` api.
+
+ :raises ValueError:
+
+ * If a keywords's value is invalid (e.g. if a ``salt`` string
+ is too small, or a ``rounds`` value is out of range).
+
+ :raises TypeError:
+
+ * if a ``kwd`` argument has an incorrect type.
+
+ .. versionadded:: 1.7
+
+.. seealso:: :ref:`hash-configuring` tutorial for a usage example
+
+Hash Inspection Methods
+=======================
+There are currently two hash inspection methods, :meth:`PasswordHash.identify`
+and :meth:`PasswordHash.needs_update`.
.. classmethod:: PasswordHash.identify(hash)
@@ -460,7 +379,7 @@ There is currently one additional support method, :meth:`~PasswordHash.identify`
If you are considering using this method to select from multiple
algorithms (e.g. in order to verify a password), you will be better served
- by the :ref:`CryptContext <context-overview>` class.
+ by the :ref:`CryptContext <context-reference>` class.
.. automethod:: PasswordHash.needs_update
@@ -476,13 +395,10 @@ There is currently one additional support method, :meth:`~PasswordHash.identify`
.. _informational-attributes:
-Informational Attributes
-========================
-
.. _general-attributes:
-General Information
--------------------
+General Informational Attributes
+================================
Each hash provides a handful of informational attributes, allowing
programs to dynamically adapt to the requirements of different
hash algorithms. The following attributes should be defined for all
@@ -501,10 +417,10 @@ the hashes in passlib:
.. attribute:: PasswordHash.setting_kwds
- Tuple listing the keywords supported by :meth:`~PasswordHash.using` control hash generation,
+ Tuple listing the keywords supported by :meth:`PasswordHash.using` control hash generation,
and which will be encoded into the resulting hash.
- (These keywords will also be accepted by :meth:`~PasswordHash.hash` and :meth:`~PasswordHash.genconfig`,
+ (These keywords will also be accepted by :meth:`PasswordHash.hash` and :meth:`PasswordHash.genconfig`,
though that behavior is deprecated as of Passlib 1.7; and will be removed in Passlib 2.0).
This list commonly includes keywords for controlling salt generation,
@@ -581,7 +497,7 @@ the hashes in passlib:
This will be present if and only if the hash truncates passwords
larger than some limit (reported via it's :attr:`truncate_size` attribute).
By default, they will silently truncate passwords above their limit.
- Setting ``truncate_error=True`` will cause :meth:`~passlib.ifc.PasswordHash.hash`
+ Setting ``truncate_error=True`` will cause :meth:`PasswordHash.hash`
to raise a :exc:`~passlib.exc.PasswordTruncateError` instead.
.. index::
@@ -590,7 +506,7 @@ the hashes in passlib:
.. _relaxed-keyword:
``relaxed``
- By default, passing an invalid value to :meth:`~PasswordHash.using`
+ By default, passing an invalid value to :meth:`PasswordHash.using`
will result in a :exc:`ValueError`. However, if ``relaxed=True``
then Passlib will attempt to correct the error and (if successful)
issue a :exc:`~passlib.exc.PasslibHashWarning` instead.
@@ -605,8 +521,8 @@ the hashes in passlib:
.. attribute:: PasswordHash.context_kwds
- Tuple listing the keywords supported by :meth:`~PasswordHash.hash`,
- :meth:`~PasswordHash.verify`, and :meth:`~PasswordHash.genhash`.
+ Tuple listing the keywords supported by :meth:`PasswordHash.hash`,
+ :meth:`PasswordHash.verify`, and :meth:`PasswordHash.genhash`.
These keywords are different from the settings kwds in that the context keywords
affect the hash, but are not encoded within it, and thus must be provided each time
the hash is calculated.
@@ -642,7 +558,7 @@ the hashes in passlib:
the correct encoding (:class:`~passlib.hash.lmhash` is perhaps the worst offender).
Hashes which provide this keyword will always expose
their default encoding programmatically via the
- :attr:`~PasswordHash.default_encoding` attribute.
+ :attr:`PasswordHash.default_encoding` attribute.
.. attribute:: truncate_size
@@ -651,15 +567,17 @@ the hashes in passlib:
the entire password provided.
Hashes which specify this setting will also support a ``truncate_error``
- flag via their :meth:`~PasswordHash.using` method, to configure
+ flag via their :meth:`PasswordHash.using` method, to configure
how truncation is handled.
+.. seealso:: :ref:`hash-configuring` tutorial for a usage example
+
.. _salt-attributes:
-Salt Information
-----------------
+Salt Information Attributes
+===========================
For schemes which support a salt string,
-``"salt"`` should be listed in their :attr:`~PasswordHash.setting_kwds`,
+``"salt"`` should be listed in their :attr:`PasswordHash.setting_kwds`,
and the following attributes should be defined:
.. attribute:: PasswordHash.max_salt_size
@@ -671,7 +589,7 @@ and the following attributes should be defined:
.. attribute:: PasswordHash.min_salt_size
The minimum number of bytes/characters required for the salt.
- Must be an integer between 0 and :attr:`~PasswordHash.max_salt_size`.
+ Must be an integer between 0 and :attr:`PasswordHash.max_salt_size`.
.. attribute:: PasswordHash.default_salt_size
@@ -697,16 +615,16 @@ and the following attributes should be defined:
.. attribute:: PasswordHash.default_salt_chars
sequence of characters used to generate new salts.
- this is typically the same as :attr:`~PasswordHash.salt_chars`, but some
+ this is typically the same as :attr:`PasswordHash.salt_chars`, but some
hashes accept a larger-than-useful range, and this will
contain only the "common" values used for generation.
.. _rounds-attributes:
-Rounds Information
-------------------
+Rounds Information Attributes
+=============================
For schemes which support a variable time-cost parameter,
-``"rounds"`` should be listed in their :attr:`~PasswordHash.setting_kwds`,
+``"rounds"`` should be listed in their :attr:`PasswordHash.setting_kwds`,
and the following attributes should be defined:
.. attribute:: PasswordHash.max_rounds
@@ -720,14 +638,14 @@ and the following attributes should be defined:
The minimum number of rounds the scheme allows.
Specifying a value below this will result in a :exc:`ValueError`.
- Will always be an integer between 0 and :attr:`~PasswordHash.max_rounds`.
+ Will always be an integer between 0 and :attr:`PasswordHash.max_rounds`.
.. attribute:: PasswordHash.default_rounds
The default number of rounds that will be used if none is explicitly
- provided to :meth:`~PasswordHash.hash`.
- This will always be an integer between :attr:`~PasswordHash.min_rounds`
- and :attr:`~PasswordHash.max_rounds`.
+ provided to :meth:`PasswordHash.hash`.
+ This will always be an integer between :attr:`PasswordHash.min_rounds`
+ and :attr:`PasswordHash.max_rounds`.
.. attribute:: PasswordHash.rounds_cost
@@ -740,6 +658,9 @@ and the following attributes should be defined:
* ``"log2"`` - time taken scales exponentially with rounds value
(e.g. :class:`~passlib.hash.bcrypt`)
+.. todo:: document the additional :meth:`PasswordHash.using` keywords
+ available for setting rounds limits.
+
..
todo: haven't decided if this is how I want the api look before
formally publishing it in the documentation:
@@ -751,7 +672,7 @@ and the following attributes should be defined:
.. note::
For the most part, applications will not need this interface,
- outside of perhaps calling the :meth:`~PasswordHash.get_backend`
+ outside of perhaps calling the :meth:`PasswordHash.get_backend`
to determine which the active backend.
Some hashes provided by Passlib have multiple backends which they
@@ -778,7 +699,7 @@ and the following attributes should be defined:
.. method:: PasswordHash.get_backend()
This method should return the name of the currently active backend
- that will be used by :meth:`!hash` and :meth:`!verify`.
+ that will be used by :meth:`PasswordHash.hash` and :meth:`PasswordHash.verify`.
:raises passlib.exc.MissingBackendError:
in the rare case that *no* backends can be loaded.
@@ -792,36 +713,7 @@ and the following attributes should be defined:
This method can be used to select a specific backend.
The ``backend`` argument must be one of the backends listed
- in :attr:`~PasswordHash.backends`, or the special value ``"default"``.
+ in :attr:`PasswordHash.backends`, or the special value ``"default"``.
:raises passlib.exc.MissingBackendError:
if the specified backend is not available.
-
-.. index:: rounds; choosing the right value
-
-.. _rounds-selection-guidelines:
-
-Choosing the right rounds value
-===============================
-For hash algorithms with a variable time-cost,
-Passlib's :attr:`~PasswordHash.default_rounds` values attempt to be secure enough for
-the average [#avgsys]_ system. But the "right" value for a given hash
-is dependant on the server, its cpu, its expected load, and its users.
-Since larger values mean increased work for an attacker,
-*the right* ``rounds`` *value for a given hash & server should be the largest
-possible value that doesn't cause intolerable delay for your users*.
-
-For most public facing services, you can generally have signin
-take upwards of 250ms - 400ms before users start getting annoyed.
-For superuser accounts, it should take as much time as the admin can stand
-(usually ~4x more delay than a regular account).
-
-Passlib's :attr:`!default_rounds` values are retuned periodically,
-starting with a rough estimate of what an "average" system is capable of,
-and then setting all :samp:`{hash}.default_rounds` values to take ~300ms on such a system.
-However, some older algorithms (e.g. :class:`~passlib.hash.bsdi_crypt`) are weak enough that
-a tradeoff must be made, choosing "secure but intolerably slow" over "fast but unacceptably insecure".
-For this reason, it is strongly recommended to not use a value much lower than Passlib's default.
-
-.. [#avgsys] For Passlib 1.6.3, all hashes were retuned to take ~300ms on a
- system with a 3.0 ghz 64 bit CPU.
diff --git a/docs/lib/passlib.context-tutorial.rst b/docs/narr/context-tutorial.rst
index 9d0cdc3..718f031 100644
--- a/docs/lib/passlib.context-tutorial.rst
+++ b/docs/narr/context-tutorial.rst
@@ -1,13 +1,12 @@
.. index:: CryptContext; overview
-.. _context-overview:
.. _context-tutorial:
.. currentmodule:: passlib.context
-==============================================
-:mod:`passlib.context` - CryptContext Tutorial
-==============================================
+===============================================
+:class:`~passlib.context.CryptContext` Tutorial
+===============================================
Overview
========
@@ -25,6 +24,8 @@ password hashes at once:
The following sections contain a walkthrough of this class, starting
with some simple examples, and working up to a complex "full-integration" example.
+.. rst-class:: float-center
+
.. seealso:: The :mod:`passlib.context` api reference,
which lists all the options and methods supported by this class.
@@ -32,8 +33,8 @@ with some simple examples, and working up to a complex "full-integration" exampl
.. rst-class:: emphasize-children
-Tutorial / Walkthrough
-======================
+Walkthrough Outline
+===================
* `Basic Usage`_
* `Using Default Settings`_
* `Loading & Saving a CryptContext`_
@@ -47,14 +48,14 @@ Tutorial / Walkthrough
.. _context-basic-example:
Basic Usage
------------
-At its base, the :class:`!CryptContext` class is just a list of
+===========
+At its base, the :class:`!CryptContext` class is just a collection of
:class:`~passlib.ifc.PasswordHash` objects, imported by name
from the :mod:`passlib.hash` module. The following snippet creates
a new context object which supports three hash algorithms
-(:doc:`sha256_crypt <passlib.hash.sha256_crypt>`,
-:doc:`md5_crypt <passlib.hash.md5_crypt>`, and
-:doc:`des_crypt <passlib.hash.des_crypt>`)::
+(:doc:`sha256_crypt </lib/passlib.hash.sha256_crypt>`,
+:doc:`md5_crypt </lib/passlib.hash.md5_crypt>`, and
+:doc:`des_crypt </lib/passlib.hash.des_crypt>`)::
>>> from passlib.context import CryptContext
>>> myctx = CryptContext(schemes=["sha256_crypt", "md5_crypt", "des_crypt"])
@@ -110,15 +111,15 @@ which probably provide a better argument for *why* you'd want to use it.
.. _context-default-settings-example:
Using Default Settings
-----------------------
+======================
While encrypting and verifying hashes is useful enough, it's not much
more than could be done by importing the objects into a list.
The next feature of the :class:`!CryptContext` class is that it
can store various customized settings for the different algorithms,
instead of hardcoding them into each :meth:`!hash` call.
-As an example, the :class:`sha256_crypt <passlib.hash.sha256_crypt>`
+As an example, the :class:`sha256_crypt </lib/passlib.hash.sha256_crypt>`
algorithm supports a ``rounds`` parameter which defaults to 80000,
-and the :class:`ldap_salted_md5 <passlib.hash.ldap_salted_md5>` algorithm uses
+and the :class:`ldap_salted_md5 </lib/passlib.hash.ldap_salted_md5>` algorithm uses
8-byte salts by default::
>>> from passlib.context import CryptContext
@@ -163,7 +164,7 @@ These is done by passing the CryptContext constructor a keyword with the format
.. _context-serialization-example:
Loading & Saving a CryptContext
--------------------------------
+===============================
The previous example built up a :class:`!CryptContext` instance
in two stages, first by calling the constructor, and then the :meth:`update`
method to make some additional changes. The same configuration
@@ -229,7 +230,7 @@ policies from the code, and into a configuration file with other security settin
.. _context-migration-example:
Deprecation & Hash Migration
-----------------------------
+============================
The final and possibly most useful feature of the :class:`CryptContext` class
is that it can take care of deprecating and migrating existing hashes,
re-hashing them using the current default algorithm and settings.
@@ -237,7 +238,7 @@ All that is required is that a few settings be added to the configuration,
and that the application call one extra method whenever a user logs in.
Deprecating Algorithms
-......................
+----------------------
The first setting that enables the hash migration features is the ``deprecated``
setting. This should be a list algorithms which are no longer desirable to have
around, but are included in ``schemes`` to provide legacy support.
@@ -275,7 +276,7 @@ check to see if the hash has been deprecated using the
strings, and other configurable behaviors that are detailed later.
Integrating Hash Migration
-..........................
+--------------------------
To summarize the process described in the previous section,
all the actions an application would usually need to
perform can be combined into the following bit of skeleton code:
@@ -312,7 +313,7 @@ that uses 2 fewer calls (and is much more efficient internally):
.. _context-min-rounds-example:
Settings Rounds Limitations
-...........................
+---------------------------
In addition to deprecating entire algorithms, the deprecations system
also allows you to place limits on algorithms that support the
variable time-cost parameter ``rounds``:
@@ -367,6 +368,12 @@ If an existing hash below the minimum is tested, it will show up as needing reha
* the :meth:`~CryptContext.needs_update` and :meth:`~CryptContext.verify_and_update` methods.
+Undocumented Features
+=====================
+
+.. todo:: Document usage of the :ref:`harden_verify <context-harden-verify-option>` option.
+.. todo:: Document usage of the :ref:`context-disabled-hashes` options.
+
.. rst-class:: html-toggle
Full Integration Example
diff --git a/docs/narr/hash-tutorial.rst b/docs/narr/hash-tutorial.rst
new file mode 100644
index 0000000..2407e63
--- /dev/null
+++ b/docs/narr/hash-tutorial.rst
@@ -0,0 +1,310 @@
+.. index::
+ single: PasswordHash interface
+ single: custom hash handler; requirements
+
+.. _hash-tutorial:
+
+.. currentmodule:: passlib.ifc
+
+===========================================
+:class:`~passlib.ifc.PasswordHash` Tutorial
+===========================================
+
+Overview
+========
+Passlib supports a large number of hash algorithms,
+all of which can be imported from the :mod:`passlib.hash` module.
+While the exact options and behavior will vary between each algorithm,
+all of the hashes provided by Passlib use the same interface,
+defined by the :class:`passlib.ifc.PasswordHash` abstract class.
+
+The :class:`!PasswordHash` class provides a generic interface for interacting
+individually with the various hashing algorithms.
+It offers methods and attributes for a number of use-cases,
+which fall into three general categories:
+
+ * Creating & verifying hashes
+
+ * Examining the configuration of a hasher,
+ and customizing the defaults.
+
+ * Assorting supplementary methods.
+
+.. seealso::
+
+ * :mod:`passlib.ifc` -- API reference of all the methods and attributes
+ of the :class:`!PasswordHash` class.
+
+ * :ref:`passlib.context.CryptContext <context-tutorial>` --
+ For working with multiple hash formats at once
+ (such a user account table with multiple existing hash formats).
+
+.. _hash-verifying:
+.. _password-hash-examples:
+
+Hashing & Verifying
+===================
+.. rst-class:: float-right without-title
+
+.. caution::
+
+ **Changed in 1.7:**
+
+ This section has changed under Passlib 1.7. Prior releases used
+ :meth:`PasswordHash.encrypt`, which has now been renamed
+ to :meth:`PasswordHash.hash`. A legacy alias is present in 1.7,
+ but will be removed in Passlib 2.0.
+
+While all the hashers in :mod:`passlib.hash` offer a range of methods and attributes,
+the main activities applications will need to perform is hashing and verifying passwords.
+
+This can be done with the :meth:`PasswordHash.hash` and :meth:`PasswordHash.verify` methods.
+
+Hashing
+-------
+First, import the desired hash. The following example uses the :class:`~passlib.hash.pbkdf2_sha256` class
+(which derives from :class:`!PasswordHash`)::
+
+ >>> # import the desired hasher
+ >>> from passlib.hash import pbkdf2_sha256
+
+Use :meth:`PasswordHash.hash` to hash a password. It takes care of unicode encoding,
+picking default rounds values::
+
+ >>> hash = pbkdf2_sha256.hash("password")
+ >>> hash
+ '$pbkdf2-sha256$29000$9t7be09prfXee2/NOUeotQ$Y.RDnnq8vsezSZSKy1QNy6xhKPdoBIwc.0XDdRm9sJ8'
+
+Note that each call generates a new salt, and thus the contents of the resulting
+hash will differ, despite using the same password::
+
+ >>> hash2 = pbkdf2_sha256.hash("password")
+ >>> hash2
+ '$pbkdf2-sha256$29000$V0rJeS.FcO4dw/h/D6E0Bg$FyLs7omUppxzXkARJQSl.ozcEOhgp3tNgNsKIAhKmp8'
+ ^^^^^^^^^^^^^^^^^^^^^^
+
+Verifying
+---------
+Subsequently, you can call :meth:`PasswordHash.verify` to check user input
+against an existing hash::
+
+ >>> pbkdf2_sha256.verify("password", hash)
+ True
+
+ >>> pbkdf2_sha256.verify("joshua", hash)
+ False
+
+.. _hash-unicode-behavior:
+
+Unicode & non-ASCII Characters
+------------------------------
+Sidenote regarding unicode passwords & non-ASCII characters:
+
+For the majority of hash algorithms and use-cases, passwords should
+be provided as either :class:`!unicode` (or ``utf-8``-encoded :class:`!bytes`).
+
+One major exception legacy hashes that were generated
+using a different character encoding. In this case, passwords should be
+encoded using the correct encoding before they are passed to :meth:`!verify`;
+otherwise users may not be able to log in successfully.
+
+.. _hash-configuring:
+
+Customizing the Configuration
+=============================
+.. rst-class:: float-right without-title
+
+.. caution::
+
+ **Changed in 1.7:**
+
+ This section has changed under Passlib 1.7. Prior releases required you
+ to pass configuration options to each call of :meth:`PasswordHash.hash`
+ That pattern is deprecated, and will be removed in Passlib 2.0;
+ code should be switched to use :meth:`PasswordHash.using`...
+
+Each hasher contains a number of :ref:`informational attributes <informational-attributes>`,
+many of which can be customized to change the properties of the hashes
+generated by :meth:`PasswordHash.hash`.
+
+Instead of modifying the hasher class directly, or having to pass in
+the options to each call to :meth:`!PasswordHash.hash`,
+all the hashes offer a :meth:`PasswordHash.using` method.
+
+This is a powerful method which accepts most hash informational attributes,
+as well as some other hash-specific configuration keywords; and returns
+a subclass of the original hasher (or an equivalent workalike). This object
+inherits the defaults from it's parent, but integrates any values you
+choose to override.
+
+As an example, if the hasher you select supports a variable number of iterations
+(such as :class:`~passlib.hash.pbkdf2_sha256`), you can specify a custom value
+using the ``rounds`` keyword.
+
+Here, the default class uses 29000 rounds::
+
+ >>> from passlib.hash import pbkdf2_sha256
+
+ >>> pbkdf2_sha256.default_rounds
+ 29000
+
+ >>> pbkdf2_sha256.hash("password")
+ '$pbkdf2-sha256$29000$V0rJeS.FcO4dw/h/D6E0Bg$FyLs7omUppxzXkARJQSl.ozcEOhgp3tNgNsKIAhKmp8'
+ ^^^^^
+
+But if we call :meth:`PasswordHash.using`, we can override this value::
+
+ >>> custom_pbkdf2 = pbkdf2_sha256.using(rounds=123456)
+ >>> custom_pbkdf2.default_rounds
+ 123456
+
+ >>> custom_pbkdf2.hash("password")
+ '$pbkdf2-sha256$123456$QwjBmJPSOsf4HyNE6L239g$8m1pnP69EYeOiKKb5sNSiYw9M8pJMyeW.CSm0KKO.GI'
+ ^^^^^^
+
+While hashes frequently have additional keywords supported by using,
+the basic set of settings you can customize can be found by inspecting
+the :attr:`PasswordHash.setting_kwds` attribute::
+
+ >>> pbkdf2_sha256.settings_kwds
+ ("salt", "salt_size", "rounds")
+
+This method is additionally used internally by the :ref:`CryptContext <context-tutorial>`
+class it order to create a custom hasher configured based on the CryptContext policy
+it was provided.
+
+.. seealso::
+
+ * :meth:`PasswordHash.using` -- API reference
+
+Context Keywords
+================
+While the :meth:`PasswordHash.hash` example above works for most hashes,
+a small number of algorithms require you provide external data
+(such as a username) every time a hash is calculated.
+
+An example of this is the :class:`~passlib.hash.oracle10` hash,
+where hashing requires a username::
+
+ >>> from passlib.hash import oracle10
+ >>> hash = oracle10.hash("secret", user="admin")
+ 'B858CE295C95193F'
+
+The difference between this and specifying something like a rounds setting
+(see :ref:`hash-configuring` above) is that a configuration option
+only needs to be specified once, and is then encoded into the hash string itself...
+Whereas a context keyword represents something that isn't stored in the hash string,
+and needs to be specified every time you call :meth:`PasswordHash.hash` **or**
+:meth:`PasswordHash.verify`::
+
+ >>> oracle10.verify("secret", hash, user="admin")
+ True
+
+In this example, if either the username OR password is wrong,
+verify() will fail::
+
+ >>> oracle10.verify("secret", hash, user="wronguser")
+ False
+
+ >>> oracle10.verify("wrongpassword", hash, user="admin")
+ False
+
+Forgetting to include a context keywords when it's required will cause a TypeError::
+
+ >>> hash = oracle10.hash("password")
+ Traceback (most recent call last):
+ <traceback omitted>
+ TypeError: user must be unicode or bytes, not None
+
+Whether a hash requires external parameters (such as ``user``)
+can be determined from its documentation page; but also programmatically from
+its :attr:`PasswordHash.context_kwds` attribute::
+
+ >>> oracle10.context_kwds
+ ("user",)
+
+ >>> pbkdf2_sha256.context_kwds
+ ()
+
+Identifying Hashes
+==================
+One of the rarer use-cases is the need to identify whether a string
+recognizably belongs to a given hasher class. This can be important
+in some cases, because attempting to call :meth:`PasswordHash.verify`
+with another algorithm's hash will result in a ValueError::
+
+ >>> from passlib.hash import pbkdf2_sha256, md5_crypt
+
+ >>> other_hash = md5_crypt.hash("password")
+
+ >>> pbkdf2_sha256.verify("password", other_hash)
+ Traceback (most recent call last):
+ <traceback omitted>
+ ValueError: not a valid pbkdf2_sha256 hash
+
+This can be prevented by using the identify method,
+which determines whether a hash belongs to a given algorithm::
+
+ >>> hash = pbkdf2_sha256.hash("password")
+ >>> pbkdf2_sha256.identify(hash)
+ True
+
+ >>> pbkdf2_sha256.identify(other_hash)
+ False
+
+Note that most cases where an application will need to use this to
+sort out multiple hash formats, it will be more useful to switch to
+a :ref:`CryptContext <context-tutorial>` object, which handles this
+(and many similar tasks) automatically.
+
+.. todo::
+
+ Document usage of :meth:`PasswordHash.needs_update`,
+ and how it ties into :meth:`PasswordHash.using`.
+
+.. index:: rounds; choosing the right value
+
+.. _rounds-selection-guidelines:
+
+Choosing the right rounds value
+===============================
+For hash algorithms with a variable time-cost,
+Passlib's :attr:`PasswordHash.default_rounds` values attempt to be secure enough for
+the average [#avgsys]_ system. But the "right" value for a given hash
+is dependant on the server, its cpu, its expected load, and its users.
+Since larger values mean increased work for an attacker...
+
+.. centered::
+ The right ``rounds`` value for a given hash & server should be the largest
+ possible value that doesn't cause intolerable delay for your users.
+
+For most public facing services, you can generally have signin
+take upwards of 250ms - 400ms before users start getting annoyed.
+For superuser accounts, it should take as much time as the admin can stand
+(usually ~4x more delay than a regular account).
+
+Passlib's :attr:`!default_rounds` values are retuned periodically,
+starting with a rough estimate of what an "average" system is capable of,
+and then setting all :samp:`{hash}.default_rounds` values to take ~300ms on such a system.
+However, some older algorithms (e.g. :class:`~passlib.hash.bsdi_crypt`) are weak enough that
+a tradeoff must be made, choosing "more secure but intolerably slow" over "fast but unacceptably insecure".
+
+For this reason, it is strongly recommended to not use a value much lower than Passlib's default,
+and to use one of :ref:`recommended hashes <recommended-hashes>`, as one of their chief qualifying
+features is the mere *existence* of rounds values which take a short enough amount of time,
+and yet are still considered secure.
+
+.. todo::
+
+ Expand this section into a full document, including
+ information from the following posts:
+
+ * http://stackoverflow.com/questions/13545677/python-passlib-what-is-the-best-value-for-rounds
+ * http://stackoverflow.com/questions/11829602/pbkdf2-and-hash-comparison
+
+ As well as maybe JS-interactive calculation helper.
+
+
+.. [#avgsys] For Passlib 1.6.3, all hashes were retuned to take ~300ms on a
+ system with a 3.0 ghz 64 bit CPU.
+
diff --git a/docs/narrative.rst b/docs/narr/index.rst
index 690354b..1c5bb0e 100644
--- a/docs/narrative.rst
+++ b/docs/narr/index.rst
@@ -14,9 +14,9 @@ Walkthrough & Tutorials
.. toctree::
:maxdepth: 2
- install
+ /install
overview
- new_app_quickstart
+ quickstart
**Tutorials**
@@ -25,5 +25,6 @@ Walkthrough & Tutorials
.. toctree::
:maxdepth: 2
- lib/passlib.context-tutorial
- lib/passlib.totp-tutorial
+ hash-tutorial
+ context-tutorial
+ totp-tutorial
diff --git a/docs/narr/overview.rst b/docs/narr/overview.rst
new file mode 100644
index 0000000..6aa73ec
--- /dev/null
+++ b/docs/narr/overview.rst
@@ -0,0 +1,92 @@
+================
+Library Overview
+================
+
+Passlib is a collection of routines for managing password hashes
+such as found in unix "shadow" files, as returned by stdlib's :func:`crypt.crypt`,
+as stored in mysql and postgres, and various other places.
+Passlib's contents can be roughly grouped into four categories:
+password hashes, password contexts, two-factor authentication,
+and other utility functions.
+
+Password Hashes
+===============
+All of the hashes supported by Passlib are implemented
+as "hasher" classes which can be imported from the :mod:`passlib.hash` module.
+In turn, all of the hashers have a uniform interface,
+which is documented in the :ref:`hash-tutorial`.
+
+*A word of warning:* the hashes in this library marked as "insecure"
+are provided for historical purposes only. Still others are specialized in ways that are not generally useful.
+If you are creating a new application and need to choose a password hash,
+see the :doc:`quickstart`.
+
+.. rst-class:: float-center
+
+.. seealso::
+
+ - :ref:`hash-tutorial` -- walkthrough of using a hasher class.
+ - :doc:`quickstart` -- if you need to choose a hash.
+ - :mod:`passlib.ifc` -- PasswordHash API reference
+ - :mod:`passlib.hash` -- list of all hashes in Passlib.
+
+Password Contexts
+=================
+Mature applications frequently have to deal with tables of existing password hashes.
+Over time, they have to support a number of tasks:
+
+* Add support for new algorithms, and deprecate old ones.
+* Raise the time-cost settings for existing algorithms as computing power increases.
+* Perform rolling upgrades of existing hashes to comply with these changes.
+* Eventually, these policies must be hardcoded in the source,
+ or time must be spent implementing a configuration language to encode them.
+
+In these situations, loading and handling multiple hash algorithms becomes
+complicated and tedious. The :mod:`passlib.context` module provides a single class,
+:class:`!CryptContext`, which attempts to solve all of these problems...
+or at least relieve applications developers of (most of) the burden.
+
+This class handles managing multiple password hash schemes,
+deprecation & migration of old hashes, and supports a simple configuration
+language that can be serialized to an INI file.
+
+.. rst-class:: float-center
+
+.. seealso::
+
+ * :ref:`context-tutorial` -- walkthrough of the CryptContext class
+ * :mod:`passlib.context` -- API reference
+
+Two-Factor Authentication
+=========================
+While not strictly connected to password hashing, modern applications frequently
+need to perform the related task of two-factor authentication. One of the most
+common protocols for doing this is TOTP (:rfc:`6238`).
+To help get TOTP in place, the :mod:`passlib.totp` module provides a set of helper functions
+for securely configuring, persisting, and verifying TOTP tokens.
+
+.. rst-class:: float-center
+
+.. seealso::
+
+ * :ref:`TOTP tutorial <totp-tutorial>` -- walkthrough of setting up TOTP integration
+ * :mod:`passlib.totp` -- API reference
+
+Application Helpers
+===================
+Passlib also provides a number of pre-configured :class:`!CryptContext` instances
+in order to get users started quickly:
+
+ * :mod:`passlib.apps` -- contains pre-configured
+ instances for managing hashes used by Postgres, Mysql, and LDAP, and others.
+
+ * :mod:`passlib.hosts` -- contains pre-configured
+ instances for managing hashes as found in the /etc/shadow files
+ on Linux and BSD systems.
+
+Passlib also contains a couple of additional modules which provide
+support for certain application-specific tasks:
+
+ * :mod:`passlib.apache` -- classes for managing htpasswd and htdigest files.
+
+ * :mod:`passlib.ext.django` -- Django plugin which monkeypatches support for (almost) any hash in Passlib.
diff --git a/docs/new_app_quickstart.rst b/docs/narr/quickstart.rst
index 51a7ae0..8e2570e 100644
--- a/docs/new_app_quickstart.rst
+++ b/docs/narr/quickstart.rst
@@ -6,34 +6,39 @@ Need to quickly get password hash support added into your new application,
and don't have time to wade through pages of documentation,
comparing and contrasting all the different schemes? Read on...
-Really Quick Start
-==================
-The fastest route is to use the preconfigured
-:data:`~passlib.apps.custom_app_context` object.
-It supports the :class:`~passlib.hash.sha256_crypt`
-and :class:`~passlib.hash.sha512_crypt` schemes,
-and defaults to 40000 hash iterations for increased strength.
-For applications which want to quickly add password hashing,
-all they need to do is the following::
-
- >>> # import the context under an app-specific name (so it can easily be replaced later)
- >>> from passlib.apps import custom_app_context as pwd_context
-
- >>> # encrypting a password...
- >>> hash = pwd_context.hash("somepass")
-
- >>> # verifying a password...
- >>> ok = pwd_context.verify("somepass", hash)
-
- >>> # [optional] encrypting a password for an admin account...
- >>> # the custom_app_context is preconfigured so that
- >>> # if the category is set to "admin" instead of None,
- >>> # it uses a stronger setting of 80000 rounds:
- >>> hash = pwd_context.hash("somepass", category="admin")
-
-For applications which started using this preset, but whose needs
-have grown beyond it, it is recommended to create your own :mod:`CryptContext <passlib.context>`
-instance; see below for more...
+..
+ NOTE: commented this out for now, considering deprecating
+ the "custom_app_context", since it's hard to convey policy changes to users.
+ May reenable if decide this is still good route to go.
+
+ Really Quick Start
+ ==================
+ The fastest route is to use the preconfigured
+ :data:`~passlib.apps.custom_app_context` object.
+ It supports the :class:`~passlib.hash.sha256_crypt`
+ and :class:`~passlib.hash.sha512_crypt` schemes,
+ and defaults to 40000 hash iterations for increased strength.
+ For applications which want to quickly add password hashing,
+ all they need to do is the following::
+
+ >>> # import the context under an app-specific name (so it can easily be replaced later)
+ >>> from passlib.apps import custom_app_context as pwd_context
+
+ >>> # encrypting a password...
+ >>> hash = pwd_context.hash("somepass")
+
+ >>> # verifying a password...
+ >>> ok = pwd_context.verify("somepass", hash)
+
+ >>> # [optional] encrypting a password for an admin account...
+ >>> # the custom_app_context is preconfigured so that
+ >>> # if the category is set to "admin" instead of None,
+ >>> # it uses a stronger setting of 80000 rounds:
+ >>> hash = pwd_context.hash("somepass", category="admin")
+
+ For applications which started using this preset, but whose needs
+ have grown beyond it, it is recommended to create your own :mod:`CryptContext <passlib.context>`
+ instance; see below for more...
.. index:: Passlib; recommended hash algorithms
@@ -42,35 +47,40 @@ instance; see below for more...
Choosing a Hash
================
-*If you already know what hash algorithm(s) you want to use,
-skip to the next section,* `Creating and Using a CryptContext`_.
If you'd like to set up a configuration that's right for your
application, the first thing to do is choose a password hashing scheme.
Passlib contains a large number of schemes, but most of them
should only be used when a specific format is explicitly required.
+.. rst-class:: float-center without-title
+
+.. seealso::
+
+ If you already know what hash algorithm(s) you want to use,
+ skip to the next section: `Creating and Using a CryptContext`_.
+
The Options
-----------
There are currently four good choices [#choices]_ for secure hashing:
* :class:`~passlib.hash.argon2`
* :class:`~passlib.hash.bcrypt`
- * :class:`~passlib.hash.sha512_crypt`
* :class:`~passlib.hash.pbkdf2_sha256` / :class:`~passlib.hash.pbkdf2_sha512`
+ * :class:`~passlib.hash.sha256_crypt` / :class:`~passlib.hash.sha512_crypt`
All four hashes share the following properties:
- * no known vulnerabilities.
- * based on documented & widely reviewed algorithms.
- * public-domain or BSD-licensed reference implementations available.
+ * No known vulnerabilities.
+ * Based on documented & widely reviewed algorithms.
+ * Public-domain or BSD-licensed reference implementations available.
* variable rounds for configuring flexible cpu cost on a per-hash basis.
- * at least 96 bits of salt.
- * basic algorithm has seen heavy scrutiny and use for at least 10 years
- (except for Argon2, born around 2013).
- * in use across a number of OSes and/or a wide variety of applications.
+ * At least 96 bits of salt.
+ * Basic algorithm has seen heavy scrutiny and use for at least 10 years
+ *(except for Argon2, born around 2013)*.
+ * In use across a number of OSes and/or a wide variety of applications.
-Argon2 is much younger than the others, but has seen heavy scrunity,
+While Argon2 is much younger than the others, it has seen heavy scrutiny,
and was purpose-designed for password hashing. In the near future, it stands likely to
become *the* recommended standard.
@@ -88,9 +98,9 @@ being much newer than the others, it has seen heavy scrutiny. Since the Argon2
had the foresight to provide not just a reference implementation, but a standard
hash encoding format, these hashes should be reliably interoperatable across all implementations.
-Issues: In it's default configuration, Argon2 uses more memory than the other hashes
-(However, this is one of it's hallmarks as a "memory hard" hashing algorithm, and contributes to it's security.
-Furthermore the exact amount used is configurable). It's only main drawback is that as of 2016-6-20
+*Issues:* In it's default configuration, Argon2 uses more memory than the other hashes.
+However, this is one of it's hallmarks as a "memory hard" hashing algorithm, and contributes to it's security.
+Furthermore the exact amount used is configurable. It's only main drawback is that as of 2016-6-20
it's only 3 years old. It's seen only a few minor adjustments since 2013,
but as it is just now gaining widespread use, the next few years are the period in which it will
likely either prove itself, or be found wanting. It's for this reason,
@@ -106,7 +116,7 @@ hashes to be readable by the native BSD crypt() function, this is the hash to us
There is also an alternative LDAP-formatted version
(:class:`~passlib.hash.ldap_bcrypt`) available.
-Issues: Neither the original Blowfish,
+*Issues:* Neither the original Blowfish,
nor the modified version which BCrypt uses, have been NIST approved;
this matter of concern is what motivated the development of SHA512-Crypt.
As well, its rounds parameter is logarithmically scaled,
@@ -116,6 +126,26 @@ of simultaneous logon attempts (e.g. web apps). Finally, BCrypt only hashes
the first 72 characters of a password, and will silently truncate longer ones
(Passlib's non-standard :class:`~passlib.hash.bcrypt_sha256` works around this last issue).
+PBKDF2
+......
+:class:`~passlib.hash.pbkdf2_sha512` is a custom hash format designed for Passlib.
+However, it directly uses the
+`PBKDF2 <http://tools.ietf.org/html/rfc2898#section-5.2>`_
+key derivation function, which was standardized in 2000, and found across a
+`wide variety <http://en.wikipedia.org/wiki/PBKDF2#Systems_that_use_PBKDF2>`_
+of applications and platforms. Unlike the previous two hashes,
+PBKDF2 has a simple and portable design,
+which is resistant (but not immune) to collision and preimage attacks
+on the underlying message digest.
+There is also :class:`~passlib.hash.pbkdf2_sha256`, which may be faster
+on 32 bit processors; as well as LDAP-formatted versions of these (
+:class:`~passlib.hash.ldap_pbkdf2_sha512` and
+:class:`~passlib.hash.ldap_pbkdf2_sha256`).
+
+*Issues:* PBKDF2 has no major security or portability issues,
+and compares favorably against bcrypt. However, bcrypt has proven slightly
+more resistant to modern GPU-based cracking techniques.
+
SHA512-Crypt
............
:class:`~passlib.hash.sha512_crypt` is
@@ -129,7 +159,7 @@ on 32 bit processors; as well as LDAP-formatted versions of these (
:class:`~passlib.hash.ldap_sha512_crypt` and
:class:`~passlib.hash.ldap_sha256_crypt`).
-Issues: Like :class:`~passlib.hash.md5_crypt`, its algorithm
+*Issues:* Like :class:`~passlib.hash.md5_crypt`, its algorithm
composes the underlying message digest hash in a baroque
and somewhat arbitrary set of combinations.
So far this "kitchen sink" design has been successful in its
@@ -156,31 +186,6 @@ via :mod:`crypt`, which will be used by Passlib.
While :class:`!sha512_crypt` uses the SHA-512 hash as a cryptographic primitive,
the algorithm's resulting password hash is far more secure.
-PBKDF2
-......
-:class:`~passlib.hash.pbkdf2_sha512` is a custom hash format designed for Passlib.
-However, it directly uses the
-`PBKDF2 <http://tools.ietf.org/html/rfc2898#section-5.2>`_
-key derivation function, which was standardized in 2000, and found across a
-`wide variety <http://en.wikipedia.org/wiki/PBKDF2#Systems_that_use_PBKDF2>`_
-of applications and platforms. Unlike the previous two hashes,
-PBKDF2 has a simple and portable design,
-which is resistant (but not immune) to collision and preimage attacks
-on the underlying message digest.
-There is also :class:`~passlib.hash.pbkdf2_sha256`, which may be faster
-on 32 bit processors; as well as LDAP-formatted versions of these (
-:class:`~passlib.hash.ldap_pbkdf2_sha512` and
-:class:`~passlib.hash.ldap_pbkdf2_sha256`).
-
-Issues: PBKDF2 has no security or portability issues.
-However, it has only come into wide use as a password hash
-in recent years; mainly hampered by the fact that there is no
-standard format for encoding password hashes using this algorithm
-(which is why Passlib has its own :ref:`custom format <mcf-pbkdf2-format>`).
-
-Furthermore, when compared to Argon2 and BCrypt, PBKDF2 has proven more susceptible to cracking
-using modern GPU-based techniques.
-
Making a Decision
-----------------
For new applications, this decision comes down to a couple of questions:
@@ -228,7 +233,7 @@ Creating and Using a CryptContext
=================================
Once you've chosen what password hash(es) you want to use,
the next step is to define a :class:`~passlib.context.CryptContext` object
-to manage your hashes, and relating configuration information.
+to manage your hashes and related policy configuration.
Insert the following code into your application::
#
@@ -240,17 +245,20 @@ Insert the following code into your application::
# create a single global instance for your app...
#
pwd_context = CryptContext(
- # replace this list with the hash(es) you wish to support.
+ # Replace this list with the hash(es) you wish to support.
# this example sets pbkdf2_sha256 as the default,
- # with support for legacy des_crypt hashes.
+ # with additional support for reading legacy des_crypt hashes.
schemes=["pbkdf2_sha256", "des_crypt"],
- default="pbkdf2_sha256",
- deprecated=["auto"],
- # set the number of rounds that should be used...
- # (appropriate values may vary for different schemes,
- # and the amount of time you wish it to take)
- pbkdf2_sha256__rounds = 29000,
+ # Automatically mark all but first hasher in list as deprecated.
+ # (this will be the default in Passlib 2.0)
+ deprecated="auto",
+
+ # Optionally, set the number of rounds that should be used.
+ # Appropriate values may vary for different schemes,
+ # and the amount of time you wish it to take.
+ # Leaving this alone is usually safe, and will use passlib's defaults.
+ ## pbkdf2_sha256__rounds = 29000,
)
To start using your CryptContext, import the context you created wherever it's needed::
@@ -269,16 +277,21 @@ To start using your CryptContext, import the context you created wherever it's n
>>> pwd_context.verify("wrongpass", hash)
False
+There's many more features packed into the context objects, read
+the walkthrough for more...
+
+.. rst-class:: float-center
+
.. seealso::
- * :mod:`passlib.hash` -- list of all hashes supported by passlib.
- * :ref:`CryptContext Overview & Tutorial <context-overview>` -- walkthrough of how to use the CryptContext class.
- * :ref:`CryptContext Reference <context-reference>` -- reference for the CryptContext api.
+ * :ref:`context-tutorial` -- full details of using the CryptContext class
+ * :mod:`passlib.context` -- CryptContext API reference
+ * :mod:`passlib.hash` -- list of all hashes supported by Passlib.
.. rubric:: Footnotes
-.. [#choices] BCrypt and PBKDF2, followed by SHA512-Crypt, are the most commonly
- used password hashes as of June 2016, when this document
- last updated. You should make sure you are reading a current
+.. [#choices] As of June 2016, the most commonly used password hashes are BCrypt and PBKDF2,
+ followed by SHA512-Crypt, with Argon2 rapidly moving up the ranks.
+ You should make sure you are reading a current
copy of the Passlib documentation, in case the state
of things has changed.
diff --git a/docs/lib/passlib.totp-tutorial.rst b/docs/narr/totp-tutorial.rst
index e76029f..f299d1d 100644
--- a/docs/lib/passlib.totp-tutorial.rst
+++ b/docs/narr/totp-tutorial.rst
@@ -4,9 +4,9 @@
.. currentmodule:: passlib.totp
-===================================
-:mod:`passlib.totp` - TOTP Tutorial
-===================================
+====================================
+:class:`~passlib.totp.TOTP` Tutorial
+====================================
Overview
========
diff --git a/docs/other.rst b/docs/other.rst
index 286bf99..ddbcb6c 100644
--- a/docs/other.rst
+++ b/docs/other.rst
@@ -6,8 +6,9 @@ Additional pages and documentation which don't fit anywhere else:
.. toctree::
:titlesonly:
+ :maxdepth: 1
faq
modular_crypt_format
- history
+ history/index
copyright
diff --git a/docs/overview.rst b/docs/overview.rst
deleted file mode 100644
index 899b7fe..0000000
--- a/docs/overview.rst
+++ /dev/null
@@ -1,81 +0,0 @@
-================
-Library Overview
-================
-
-Passlib is a collection of routines for managing password hashes
-such as found in unix "shadow" files, as returned by stdlib's :func:`!crypt`,
-as stored in mysql and postgres, and various other places.
-Passlib's contents can be roughly grouped into three categories:
-password hashes, password contexts, and utility functions.
-
-Password Hashes
-===============
-All of the hash schemes supported by Passlib are implemented
-as classes which can be imported from the :mod:`passlib.hash` module.
-In turn, all of the hash classes implement a single uniform interface,
-which is documented in detail and with usage examples in the
-:ref:`password-hash-api` document.
-However, many of these hashes are severely insecure, provided only for legacy
-purposes, or are specialized in ways that are not generally useful.
-If you are creating a new application and need to choose a password hash,
-see the :doc:`new_app_quickstart`.
-
-.. seealso::
-
- - :mod:`passlib.hash` -- all the hashes supported by Passlib.
- - :ref:`password-hash-api` -- documentation of the common PasswordHash interface.
- - :doc:`new_app_quickstart` -- choosing a hash for new applications.
-
-Password Contexts
-=================
-Mature applications frequently have to deal with tables of existing password hashes.
-Over time, they have to support a number of tasks:
-
-* add support for new algorithms, and deprecate old ones,
-* raise the time-cost settings for existing algorithms, as computing power increases,
-* and do rolling upgrades of existing hashes to comply with these changes.
-* hardcode these policies in the source, or spend time implementing
- a configuration language for them.
-
-In these situations, loading and handling multiple hash algorithms becomes
-complicated and tedious. The :mod:`passlib.context` module provides a single class,
-:class:`!CryptContext`, which attempts to solve all of these problems,
-or at least relieve applications developers of (most of) the burden.
-This class handles managing multiple password hash schemes,
-deprecation & migration of old hashes, and supports a simple configuration
-language that can be serialized to an INI file.
-
-.. seealso::
-
- * :ref:`CryptContext Tutorial <context-tutorial>` -- complete walkthrough of the CryptContext class.
- * :ref:`CryptContext API Reference <context-reference>` -- full method and attribute documentation.
-
-Application Helpers
-===================
-Passlib also provides a number of pre-configured :class:`!CryptContext` instances
-in order to get users started quickly:
-
- * :mod:`passlib.apps` -- contains pre-configured
- instances for managing hashes used by Postgres, Mysql, and LDAP, and others.
-
- * :mod:`passlib.hosts` -- contains pre-configured
- instances for managing hashes as found in the /etc/shadow files
- on Linux and BSD systems.
-
-Passlib also contains a couple of additional modules which provide
-support for certain application-specific tasks:
-
- * :mod:`passlib.apache` -- classes for managing htpasswd and htdigest files.
-
- * :mod:`passlib.ext.django` -- Django plugin which monkeypatches support for (almost) any hash in Passlib.
-
-Utility Functions
-=================
-Additionally, Passlib contains a number of modules which are used internally
-to implement the all of the other features. These may change between major
-releases, and won't be needed by most users of Passlib. They are documented
-mainly to aid in examining the source.
-
- * :mod:`passlib.exc` -- all the custom errors & warnings used by Passlib.
- * :mod:`passlib.registry` -- functions for registering password hash algorithms.
- * :mod:`passlib.utils` -- support functions for implementing password hashes.
diff --git a/docs/reference.rst b/docs/reference.rst
deleted file mode 100644
index 50d24ec..0000000
--- a/docs/reference.rst
+++ /dev/null
@@ -1,40 +0,0 @@
-=============
-API Reference
-=============
-
-The reference section contains documentation of Passlib's public API.
-These chapters are focused on providing detailed reference of the individual
-functions and classes; they will generally be cross-linked to any related walkthrough
-documentation (which tries to provide a higher-level synthetic view).
-
-**Primary modules of interest:**
-
-* :doc:`lib/passlib.context`
-* :doc:`lib/passlib.hash`
-* :doc:`lib/passlib.totp`
-* :doc:`lib/passlib.exc`
-
-**Full module list:**
-
-..
- TODO: instead of max-depth, implement html toggling
-
-.. toctree::
- :titlesonly:
- :maxdepth: 1
-
- lib/passlib.apache
- lib/passlib.apps
- lib/passlib.exc
- lib/passlib.context
- lib/passlib.crypto
- lib/passlib.ext.django
- lib/passlib.hash
- lib/passlib.hosts
- password_hash_api
- lib/passlib.pwd
- lib/passlib.registry
- lib/passlib.totp
- lib/passlib.utils
-
-
diff --git a/passlib/crypto/digest.py b/passlib/crypto/digest.py
index 78c2ad4..2d8006a 100644
--- a/passlib/crypto/digest.py
+++ b/passlib/crypto/digest.py
@@ -207,18 +207,22 @@ def lookup_hash(digest, return_unknown=False):
Can be used to look up a hash constructor by name, normalize hash name representation, etc.
:arg digest:
- A string containing a :mod:`!hashlib` digest name (e.g. ``"sha256"``),
- an IANA-assigned hash name, or even a digest constructor (e.g. :func:`hashlib.sha256`).
+ This can be any of:
+
+ * A string containing a :mod:`!hashlib` digest name (e.g. ``"sha256"``),
+ * A string containing an IANA-assigned hash name,
+ * A digest constructor function (e.g. ``hashlib.sha256``).
+
Case is ignored, underscores are converted to hyphens,
and various other cleanups are made.
:param return_unknown:
- By default, this function will throw a :exc:`~passlib.exc.KnownHashError` if no hash constructor
+ By default, this function will throw an :exc:`~passlib.exc.UnknownHashError` if no hash constructor
can be found. However, if this flag is False, it will instead return a dummy record
without a constructor function. This is mainly used by :func:`norm_hash_name`.
:returns HashInfo:
- :class:`!HashInfo` instance containing information about specified digest.
+ :class:`HashInfo` instance containing information about specified digest.
Multiple calls resolving to the same hash should always
return the same :class:`!HashInfo` instance.
@@ -323,8 +327,8 @@ def norm_hash_name(name, format="hashlib"):
with Python's :mod:`!hashlib`.
* ``"iana"`` - normalizes name to IANA-assigned hash function name.
- for hashes which IANA hasn't assigned a name for, issues a warning,
- and then uses a heuristic to give a "best guess".
+ For hashes which IANA hasn't assigned a name for, this issues a warning,
+ and then uses a heuristic to return a "best guess" name.
:returns:
Hash name, returned as native :class:`!str`.
diff --git a/passlib/handlers/bcrypt.py b/passlib/handlers/bcrypt.py
index 91d5840..8f8cd62 100644
--- a/passlib/handlers/bcrypt.py
+++ b/passlib/handlers/bcrypt.py
@@ -695,7 +695,7 @@ class _PyBcryptBackend(_BcryptCommon):
#-----------------------------------------------------------------------
class _OsCryptBackend(_BcryptCommon):
"""
- backend which uses os.crypt()
+ backend which uses :func:`crypt.crypt`
"""
@classmethod
diff --git a/passlib/pwd.py b/passlib/pwd.py
index 7e7be91..580acd3 100644
--- a/passlib/pwd.py
+++ b/passlib/pwd.py
@@ -434,7 +434,7 @@ def genword(entropy=None, length=None, returns=None, **kwds):
based on the requested entropy amount, and the size of the character set.
If both ``entropy`` and ``length`` are specified,
- the larger effective length will be used.
+ the stronger value will be used.
This can also be one of a handful of aliases to predefined
entropy amounts: ``"weak"`` (24), ``"fair"`` (36),
@@ -453,9 +453,9 @@ def genword(entropy=None, length=None, returns=None, **kwds):
:param charset:
The character set to draw from, if not specified explicitly by **chars**.
- Defaults to ``"ascii_62"``, but can be any of:
+ Can be any of:
- * ``"ascii_62"`` -- all digits and ascii upper & lowercase letters.
+ * ``"ascii_62"`` (the default) -- all digits and ascii upper & lowercase letters.
Provides ~5.95 entropy per character.
* ``"ascii_50"`` -- subset which excludes visually similar characters
@@ -697,7 +697,7 @@ def genphrase(entropy=None, length=None, returns=None, **kwds):
based on the requested entropy amount, and the size of the character set.
If both ``entropy`` and ``length`` are specified,
- the larger effective length will be used.
+ the stronger value will be used.
This can also be one of a handful of aliases to predefined
entropy amounts: ``"weak"`` (24), ``"fair"`` (36),
diff --git a/passlib/registry.py b/passlib/registry.py
index 44076c7..fe6cc6a 100644
--- a/passlib/registry.py
+++ b/passlib/registry.py
@@ -509,7 +509,7 @@ def has_backend(hasher, backend=ANY, safe=False):
@memoize_single_value
def get_supported_os_crypt_schemes():
"""
- return tuple of schemes which :func:`os.crypt` natively supports.
+ return tuple of schemes which :func:`crypt.crypt` natively supports.
"""
if not os_crypt_present:
return ()
@@ -525,7 +525,7 @@ def get_supported_os_crypt_schemes():
# TODO: needs UTs
def has_os_crypt_support(hasher):
"""
- check if hash is supported by native :func:`os.crypt` function.
+ check if hash is supported by native :func:`crypt.crypt` function.
if :func:`crypt.crypt` is not present, will always return False.
:param hasher:
diff --git a/setup.py b/setup.py
index dc44045..4a2ae67 100644
--- a/setup.py
+++ b/setup.py
@@ -88,7 +88,7 @@ providing full-strength password hashing for multi-user applications.
* See the `homepage <https://bitbucket.org/ecollins/passlib>`_
for the latest news and more information.
-* See the `changelog <https://passlib.readthedocs.io/en/stable/history.html>`_
+* See the `changelog <https://passlib.readthedocs.io/en/stable/history>`_
for a description of what's new in Passlib.
All releases are signed with the gpg key