summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Collins <elic@assurancetechnologies.com>2012-04-27 02:53:52 -0400
committerEli Collins <elic@assurancetechnologies.com>2012-04-27 02:53:52 -0400
commit8c913e33b59a7f37dd7545ae8e4b0258e12c5dc3 (patch)
tree894d77134588198d507647c26e19ca3c12473aca
parentb308b88118d1bb14f1adb5513d7290b25dda1e31 (diff)
downloadpasslib-8c913e33b59a7f37dd7545ae8e4b0258e12c5dc3.tar.gz
merging rewrite of all hash documentation, and password hash api
* password hash api rewritten to center around PasswordHash abstract class * extended walkthrough and documentation for PasswordHash interface * pared down the per-hash examples, added links to PasswordHash * updates docs and warnings
-rw-r--r--docs/lib/passlib.hash.apr_md5_crypt.rst17
-rw-r--r--docs/lib/passlib.hash.atlassian_pbkdf2_sha1.rst13
-rw-r--r--docs/lib/passlib.hash.bcrypt.rst72
-rw-r--r--docs/lib/passlib.hash.bigcrypt.rst45
-rw-r--r--docs/lib/passlib.hash.bsdi_crypt.rst46
-rw-r--r--docs/lib/passlib.hash.cisco_pix.rst71
-rw-r--r--docs/lib/passlib.hash.cisco_type7.rst58
-rw-r--r--docs/lib/passlib.hash.crypt16.rst32
-rw-r--r--docs/lib/passlib.hash.cta_pbkdf2_sha1.rst14
-rw-r--r--docs/lib/passlib.hash.des_crypt.rst50
-rw-r--r--docs/lib/passlib.hash.django_std.rst142
-rw-r--r--docs/lib/passlib.hash.dlitz_pbkdf2_sha1.rst14
-rw-r--r--docs/lib/passlib.hash.fshp.rst50
-rw-r--r--docs/lib/passlib.hash.grub_pbkdf2_sha512.rst11
-rw-r--r--docs/lib/passlib.hash.hex_digests.rst51
-rw-r--r--docs/lib/passlib.hash.ldap_crypt.rst55
-rw-r--r--docs/lib/passlib.hash.ldap_other.rst5
-rw-r--r--docs/lib/passlib.hash.ldap_pbkdf2_digest.rst2
-rw-r--r--docs/lib/passlib.hash.ldap_std.rst50
-rw-r--r--docs/lib/passlib.hash.lmhash.rst34
-rw-r--r--docs/lib/passlib.hash.md5_crypt.rst44
-rw-r--r--docs/lib/passlib.hash.msdcc.rst46
-rw-r--r--docs/lib/passlib.hash.msdcc2.rst32
-rw-r--r--docs/lib/passlib.hash.mssql2000.rst36
-rw-r--r--docs/lib/passlib.hash.mssql2005.rst34
-rw-r--r--docs/lib/passlib.hash.mysql323.rst41
-rw-r--r--docs/lib/passlib.hash.mysql41.rst26
-rw-r--r--docs/lib/passlib.hash.nthash.rst34
-rw-r--r--docs/lib/passlib.hash.oracle10.rst50
-rw-r--r--docs/lib/passlib.hash.oracle11.rst40
-rw-r--r--docs/lib/passlib.hash.pbkdf2_digest.rst57
-rw-r--r--docs/lib/passlib.hash.phpass.rst15
-rw-r--r--docs/lib/passlib.hash.plaintext.rst38
-rw-r--r--docs/lib/passlib.hash.postgres_md5.rst37
-rw-r--r--docs/lib/passlib.hash.rst105
-rw-r--r--docs/lib/passlib.hash.scram.rst80
-rw-r--r--docs/lib/passlib.hash.sha1_crypt.rst28
-rw-r--r--docs/lib/passlib.hash.sha256_crypt.rst118
-rw-r--r--docs/lib/passlib.hash.sha512_crypt.rst125
-rw-r--r--docs/lib/passlib.hash.sun_md5_crypt.rst21
-rw-r--r--docs/lib/passlib.hash.unix_disabled.rst30
-rw-r--r--docs/password_hash_api.rst975
-rw-r--r--passlib/handlers/bcrypt.py26
-rw-r--r--passlib/handlers/cisco.py11
-rw-r--r--passlib/handlers/des_crypt.py31
-rw-r--r--passlib/handlers/django.py52
-rw-r--r--passlib/handlers/fshp.py4
-rw-r--r--passlib/handlers/ldap_digests.py31
-rw-r--r--passlib/handlers/md5_crypt.py13
-rw-r--r--passlib/handlers/misc.py20
-rw-r--r--passlib/handlers/mssql.py6
-rw-r--r--passlib/handlers/mysql.py4
-rw-r--r--passlib/handlers/oracle.py10
-rw-r--r--passlib/handlers/pbkdf2.py37
-rw-r--r--passlib/handlers/phpass.py8
-rw-r--r--passlib/handlers/postgres.py7
-rw-r--r--passlib/handlers/scram.py21
-rw-r--r--passlib/handlers/sha1_crypt.py12
-rw-r--r--passlib/handlers/sha2_crypt.py28
-rw-r--r--passlib/handlers/sun_md5_crypt.py6
-rw-r--r--passlib/handlers/windows.py22
61 files changed, 1701 insertions, 1492 deletions
diff --git a/docs/lib/passlib.hash.apr_md5_crypt.rst b/docs/lib/passlib.hash.apr_md5_crypt.rst
index ee4ac73..2c67de5 100644
--- a/docs/lib/passlib.hash.apr_md5_crypt.rst
+++ b/docs/lib/passlib.hash.apr_md5_crypt.rst
@@ -8,15 +8,15 @@
This format is a variation of :class:`~passlib.hash.md5_crypt`,
primarily used by the Apache webserver in ``htpasswd`` files.
-It contains only minor changes to md5-crypt, and should
-be considered just as strong / weak as md5-crypt itself.
+It contains only minor changes to the md5-crypt algorithm,
+and should be considered just as strong / weak as md5-crypt itself.
-.. seealso:: :doc:`md5_crypt <passlib.hash.md5_crypt>`, :mod:`passlib.apache`
+.. seealso::
-Usage
-=====
-This algorithm can be used in exactly the same way as :class:`~passlib.hash.md5_crypt`,
-see that class for details.
+ * :ref:`password hash usage <password-hash-examples>` --
+ for examples of how to use this class via the common hash interface.
+
+ * :mod:`passlib.apache` -- routines for manipulating ``htpasswd`` files.
Interface
=========
@@ -34,6 +34,9 @@ to the original MD5-Crypt, except for two changes:
Because of this change, even raw checksums generated by apr-md5-crypt and md5-crypt
are not compatible with eachother.
+See :doc:`md5_crypt <passlib.hash.md5_crypt>` for the format & algorithm
+descriptions, as well as security notes.
+
.. rubric:: Footnotes
.. [#] Apache's description of Apr-MD5-Crypt -
diff --git a/docs/lib/passlib.hash.atlassian_pbkdf2_sha1.rst b/docs/lib/passlib.hash.atlassian_pbkdf2_sha1.rst
index 4bd4892..a725cbe 100644
--- a/docs/lib/passlib.hash.atlassian_pbkdf2_sha1.rst
+++ b/docs/lib/passlib.hash.atlassian_pbkdf2_sha1.rst
@@ -17,14 +17,11 @@ used in new applications.
.. seealso::
- :doc:`passlib.hash.pbkdf2_digest <passlib.hash.pbkdf2_digest>`
- for some other PBKDF2-based hashes.
-
-Usage
-=====
-These classes support both rounds and salts,
-and can be used in the exact same manner
-as :doc:`SHA-512 Crypt <passlib.hash.sha512_crypt>`.
+ * :ref:`password hash usage <password-hash-examples>` --
+ for examples of how to use this class via the common hash interface.
+
+ * :doc:`passlib.hash.pbkdf2_{digest} <passlib.hash.pbkdf2_digest>` --
+ for some other PBKDF2-based hashes.
Interface
=========
diff --git a/docs/lib/passlib.hash.bcrypt.rst b/docs/lib/passlib.hash.bcrypt.rst
index 50eba4f..cb09e37 100644
--- a/docs/lib/passlib.hash.bcrypt.rst
+++ b/docs/lib/passlib.hash.bcrypt.rst
@@ -9,46 +9,62 @@ It uses a modified version of the Blowfish stream cipher. Featuring
a large salt and variable number of rounds, it's currently the default
password hash for many systems (notably BSD), and has no known weaknesses.
It is one of the three hashes Passlib :ref:`recommends <recommended-hashes>`
-for new applications.
-
-.. note::
-
- It is strongly recommended to install
- :ref:`py-bcrypt or bcryptor <optional-libraries>`
- if this algorithm is going to be used.
-
-Usage
-=====
-This class can be used directly as follows::
+for new applications. This class can be used directly as follows::
>>> from passlib.hash import bcrypt
- >>> #generate new salt, encrypt password
+ >>> # generate new salt, encrypt password
>>> h = bcrypt.encrypt("password")
>>> h
'$2a$12$NT0I31Sa7ihGEWpka9ASYrEFkhuTNeBQ2xfZskIiiJeyFXhRgS.Sy'
- >>> #same, but with explict number of rounds
+ >>> # the same, but with an explicit number of rounds
>>> bcrypt.encrypt("password", rounds=8)
'$2a$08$8wmNsdCH.M21f.LSBSnYjQrZ9l1EmtBc9uNPGL.9l75YE8D8FlnZC'
- >>> #check if hash is a bcrypt hash
- >>> bcrypt.identify(h)
- True
- >>> #check if some other hash is recognized
- >>> bcrypt.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31')
- False
-
- >>> #verify correct password
+ >>> #verify password
>>> bcrypt.verify("password", h)
True
- >>> #verify incorrect password
>>> bcrypt.verify("wrong", h)
False
+.. note::
+
+ It is strongly recommended to install
+ :ref:`py-bcrypt or bcryptor <optional-libraries>`
+ if this algorithm is going to be used.
+
+.. seealso:: :ref:`password hash usage <password-hash-examples>` for more examples
+
Interface
=========
-.. autoclass:: bcrypt
+.. autoclass:: bcrypt()
+
+.. note::
+
+ This class will use the first available of four possible backends:
+
+ 1. `py-bcrypt <http://www.mindrot.org/projects/py-bcrypt/>`_, if installed.
+ 2. `bcryptor <https://bitbucket.org/ares/bcryptor/overview>`_, if installed.
+ 3. stdlib's :func:`crypt.crypt()`, if the host OS supports BCrypt
+ (primarily BSD-derived systems).
+ 4. A *slow* pure-python implementation of BCrypt, built into Passlib.
+
+ It should be noted that the builtin pure-python implementation is too slow
+ to be both secure and responsive at the same time (except under PyPy > 1.7)
+ Because of this, it is disabled by default, unless
+ the environment variable ``PASSLIB_BUILTIN_BCRYPT="enabled"`` has been set
+ before Passlib is first loaded.
+
+ If the first three backends are not available, and the builtin
+ backend has not been enabled, :meth:`encrypt` and :meth:`verify`
+ will throw a :exc:`~passlib.exc.MissingBackendError` when they are called.
+
+ You can see which backend is in use by calling the :meth:`get_backend()` method.
+
+.. versionchanged:: 1.6
+ The pure-python backend was added, though it's disabled by default
+ for security. (speedups are welcome!)
Format & Algorithm
==================
@@ -74,7 +90,7 @@ This implementation of bcrypt differs from others in a few ways:
BCrypt does not specify what the behavior should be when
passed a salt string outside of the regexp range ``[./A-Za-z0-9]``.
- In order to avoid this situtation, PassLib strictly limits salts to the
+ In order to avoid this situtation, Passlib strictly limits salts to the
allowed character set, and will throw a ValueError if an invalid
salt character is encountered.
@@ -87,10 +103,10 @@ This implementation of bcrypt differs from others in a few ways:
as well as all known reference hashes.
In order to provide support for unicode strings,
- PassLib will encode unicode passwords using ``utf-8``
+ Passlib will encode unicode passwords using ``utf-8``
before running them through bcrypt. If a different
encoding is desired by an application, the password should be encoded
- before handing it to PassLib.
+ before handing it to Passlib.
* Padding Bits
@@ -105,7 +121,9 @@ This implementation of bcrypt differs from others in a few ways:
(This behavior will eventually be deprecated and such hashes
will throw a :exc:`ValueError` instead).
-* crypt_blowfish 2x/2y hashes
+* the crypt_blowfish bug, and the 2x/2y hashes
+
+ .. _crypt-blowfish-bug:
Pre-1.1 versions of the `crypt_blowfish <http://www.openwall.com/crypt/>`_
bcrypt implementation suffered from a serious flaw [#eight]_
diff --git a/docs/lib/passlib.hash.bigcrypt.rst b/docs/lib/passlib.hash.bigcrypt.rst
index 5f2429e..d7e8b24 100644
--- a/docs/lib/passlib.hash.bigcrypt.rst
+++ b/docs/lib/passlib.hash.bigcrypt.rst
@@ -2,21 +2,21 @@
:class:`passlib.hash.bigcrypt` - BigCrypt
=======================================================================
-.. currentmodule:: passlib.hash
-
-This class implements BigCrypt (a modified version of des-crypt) commonly
-found on HP-UX, Digital Unix, and OSF/1. The main difference with
-:class:`~passlib.hash.des_crypt` is that bigcrypt
-uses all the characters of a password, not just the first 8,
-and has a variable length hash string.
-
.. warning::
This algorithm is dangerously weak, and should not be used if at all possible.
-Usage
-=====
-This class can be used in exactly the same manner as :class:`~passlib.hash.des_crypt`.
+.. currentmodule:: passlib.hash
+
+This class implements BigCrypt (a modified version of DES-Crypt) commonly
+found on HP-UX, Digital Unix, and OSF/1. The main difference between it and
+:class:`~passlib.hash.des_crypt` is that BigCrypt
+uses all the characters of a password, not just the first 8,
+and has a variable length hash.
+
+.. seealso::
+ :ref:`password hash usage <password-hash-examples>` --
+ for examples of how to use this class via the common hash interface.
Interface
=========
@@ -37,6 +37,19 @@ A bigcrypt hash string has the format :samp:`{salt}{checksum_1}{checksum_2...}{c
* the integer :samp:`n` (the number of checksums) is determined by the formula
:samp:`{n}=min(1, (len({secret})+7)//8)`.
+.. note::
+
+ This hash format lacks any magic prefix that can be used to unambiguously
+ identify it. Out of context, certain :class:`!bigcrypt` hashes may
+ be confused with that of two other algorithms:
+
+ * :class:`des_crypt` - BigCrypt hashes of passwords with < 8 characters
+ are exactly the same as the Des-Crypt hash of the same password.
+
+ * :class:`crypt16` - BigCrypt hashes of passwords with
+ 9 to 16 characters have the same size and character set as
+ Crypt-16 hashes; though the actual algorithms are different.
+
.. rst-class:: html-toggle
Algorithm
@@ -95,7 +108,7 @@ BigCrypt is dangerously flawed:
* It suffers from all the flaws of :class:`~passlib.hash.des_crypt`.
-* Since checksum in it's hash is essentially a separate
+* Since each checksum compontent in it's hash is essentially a separate
des-crypt checksum, they can be attacked in parallel.
* It reveals information about the length of the encoded
@@ -117,8 +130,8 @@ This implementation of bigcrypt differs from others in two ways:
various limits on maximum password length (commonly, 128 chars),
and discard the remaining part of the password.
- Thus, while PassLib should be able to verify all existing
- bigcrypt hashes, other systems may require hashes generated by PassLib
+ Thus, while Passlib should be able to verify all existing
+ bigcrypt hashes, other systems may require hashes generated by Passlib
to be truncated to their specific maximum length.
* Unicode Policy:
@@ -127,10 +140,10 @@ This implementation of bigcrypt differs from others in two ways:
(as evidenced by the fact that it discards the 8th bit of all password bytes).
In order to provide support for unicode strings,
- PassLib will encode unicode passwords using ``utf-8``
+ Passlib will encode unicode passwords using ``utf-8``
before running them through bigcrypt. If a different
encoding is desired by an application, the password should be encoded
- before handing it to PassLib.
+ before handing it to Passlib.
.. rubric:: Footnotes
diff --git a/docs/lib/passlib.hash.bsdi_crypt.rst b/docs/lib/passlib.hash.bsdi_crypt.rst
index 8a1b9af..c8e4b9b 100644
--- a/docs/lib/passlib.hash.bsdi_crypt.rst
+++ b/docs/lib/passlib.hash.bsdi_crypt.rst
@@ -4,39 +4,49 @@
.. currentmodule:: passlib.hash
+.. note::
+
+ This algorithm is weak by modern standards, and should not be used in new applications.
+
This algorithm was developed by BSDi for their BSD/OS distribution.
It's based on :class:`~passlib.hash.des_crypt`, and contains a larger
salt and a variable number of rounds. This algorithm is also
known as "Extended DES Crypt".
-This algorithm is weak by modern standards,
-and should not be used in new applications.
-
-Usage
-=====
-This class can be used directly as follows::
+It class can be used directly as follows::
- >>> from passlib.hash import bsdi_crypt as bc
+ >>> from passlib.hash import bsdi_crypt
- >>> bc.encrypt("password") #generate new salt, encrypt password
+ >>> # generate new salt, encrypt password
+ >>> hash = bsdi_crypt.encrypt("password")
+ >>> hash
'_7C/.Bf/4gZk10RYRs4Y'
- >>> bc.encrypt("password", rounds=10001) #same, but with explict number of rounds
+ >>> # same, but with explict number of rounds
+ >>> bsdi_crypt.encrypt("password", rounds=10001)
'_FQ0.amG/zwCMip7DnBk'
- >>> bc.identify('_7C/.Bf/4gZk10RYRs4Y') #check if hash is recognized
+ >>> # verify password
+ >>> bsdi_crypt.verify("password", hash)
True
- >>> bc.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31') #check if some other hash is recognized
+ >>> bsdi_crypt.verify("secret", hash)
False
- >>> bc.verify("password", '_7C/.Bf/4gZk10RYRs4Y') #verify correct password
- True
- >>> bc.verify("secret", '_7C/.Bf/4gZk10RYRs4Y') #verify incorrect password
- False
+.. seealso:: :ref:`password hash usage <password-hash-examples>` for more examples
Interface
=========
.. autoclass:: bsdi_crypt()
+.. note::
+
+ This class will use the first available of two possible backends:
+
+ * stdlib :func:`crypt()`, if the host OS supports BSDi-Crypt
+ (primarily BSD-derived systems).
+ * a pure Python implementation of BSDi-Crypt built into Passlib.
+
+ You can see which backend is in use by calling the :meth:`get_backend()` method.
+
Format
======
An example hash (of the string ``password``) is ``_EQ0.jzhSVeUyoSqLupI``.
@@ -97,6 +107,8 @@ The checksum is formed by a modified version of the DES cipher in encrypt mode:
9. The resulting 66-bit integer is encoded in big-endian order
using the :data:`hash64-big <passlib.utils.h64big>` format.
+.. _bsdi-crypt-security-issues:
+
Security Issues
===============
BSDi Crypt should not be considered sufficiently secure, for a number of reasons:
@@ -131,10 +143,10 @@ This implementation of bsdi-crypt differs from others in one way:
(as evidenced by the fact that it discards the 8th bit of all password bytes).
In order to provide support for unicode strings,
- PassLib will encode unicode passwords using ``utf-8``
+ Passlib will encode unicode passwords using ``utf-8``
before running them through bsdi-crypt. If a different
encoding is desired by an application, the password should be encoded
- before handing it to PassLib.
+ before handing it to Passlib.
.. rubric:: Footnotes
diff --git a/docs/lib/passlib.hash.cisco_pix.rst b/docs/lib/passlib.hash.cisco_pix.rst
index 52ee277..cb15639 100644
--- a/docs/lib/passlib.hash.cisco_pix.rst
+++ b/docs/lib/passlib.hash.cisco_pix.rst
@@ -4,70 +4,63 @@
:class:`passlib.hash.cisco_pix` - Cisco PIX hash
==================================================================
-.. currentmodule:: passlib.hash
-
-This class implements the password hash algorithm commonly found on Cisco
-PIX firewalls.
+.. versionadded:: 1.6
.. warning::
This hash is not secure, and should not be used for any purposes
besides manipulating existing Cisco PIX password hashes.
-.. seealso::
-
- * :doc:`passlib.hash.md5_crypt` (referred to as a "type 5" hash by Cisco)
- * :doc:`passlib.hash.cisco_type7`
-
-Usage
-=====
-.. note::
-
- This hash algorithm has a context-sensitive percularity.
- It takes in an optional username, used to salt the hash,
- but with specific restrictions...
-
- * The username *must* be provided in order to correctly hash passwords
- associated with a user account on the Cisco device.
-
- * Conversely, the username *must not* be provided (or must be set to ``""``)
- in order to correctly hash passwords which don't have an associated user
- account (such as the "enable" password).
+.. currentmodule:: passlib.hash
-This class can be used directly as follows::
+This class implements the password hash algorithm commonly found on Cisco
+PIX firewalls. This class can be used directly as follows::
>>> from passlib.hash import cisco_pix as pix
>>> # encrypt password using specified username
- >>> h = pix.encrypt("password", "user")
- >>> h
+ >>> hash = pix.encrypt("password", user="user")
+ >>> hash
'A5XOy94YKDPXCo7U'
- >>> pix.identify(h) #check if hash is recognized
+ >>> #verify correct password
+ >>> pix.verify("password", hash, user="user")
True
- >>> pix.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31') #check if some other hash is recognized
+ >>> #verify correct password w/ wrong username
+ >>> pm.verify("password", hash, user="other")
False
-
- >>> pix.verify("password", h, "user") #verify correct password
- True
- >>> pm.verify("password", h, "other") #verify correct password w/ wrong username
- False
- >>> pm.verify("letmein", h, "user") #verify incorrect password
+ >>> #verify incorrect password
+ >>> pm.verify("letmein", hash, user="user")
False
>>> # encrypt password without associate user account
- >>> h2 = pix.encrypt("password")
- >>> h2
+ >>> hash2 = pix.encrypt("password")
+ >>> hash2
'NuLKvvWGg.x9HEKO'
>>> # verify password without associated user account
- >>> pix.verify("password", h2)
+ >>> pix.verify("password", hash2)
True
+.. seealso:: :ref:`password hash usage <password-hash-examples>` for more examples
+
Interface
=========
.. autoclass:: cisco_pix()
+.. note::
+
+ This hash algorithm has a context-sensitive percularity.
+ It takes in an optional username, used to salt the hash,
+ but with specific restrictions...
+
+ * The username *must* be provided in order to correctly hash passwords
+ associated with a user account on the Cisco device.
+
+ * Conversely, the username *must not* be provided (or must be set to ``""``)
+ in order to correctly hash passwords which don't have an associated user
+ account (such as the "enable" password).
+
.. rst-class:: html-toggle
Format & Algorithm
@@ -127,10 +120,10 @@ This implementation differs from the standard in one main way:
how it handles other characters is not known.
In order to provide support for unicode strings,
- PassLib will encode unicode passwords using ``utf-8``
+ Passlib will encode unicode passwords using ``utf-8``
before running them through this algorithm. If a different
encoding is desired by an application, the password should be encoded
- before handing it to PassLib.
+ before handing it to Passlib.
* While this implementation agrees with all known references,
the actual algorithm has not been published by Cisco, so there may be other
diff --git a/docs/lib/passlib.hash.cisco_type7.rst b/docs/lib/passlib.hash.cisco_type7.rst
index 7d9c83b..1fdb9d3 100644
--- a/docs/lib/passlib.hash.cisco_type7.rst
+++ b/docs/lib/passlib.hash.cisco_type7.rst
@@ -4,56 +4,48 @@
:class:`passlib.hash.cisco_type7` - Cisco "Type 7" hash
==================================================================
-.. currentmodule:: passlib.hash
+.. versionadded:: 1.6
-This class implements the "Type 7" password encoding used Cisco IOS.
-This is not actually a true hash, but a reversible encoding of the plaintext
-password. Type 7 strings are (and were designed to be) **plaintext equivalent**;
-the goal was to protect from "over the shoulder" eavesdropping, and
-little else. They can be trivially decoded. **Do not use for any purpose
-where actual security is needed**.
+.. warning::
-.. note::
+ This is not a hash, this is a reversible plaintext encoding.
+ **This format can be trivially decoded**.
- This implementation should work correctly for most cases, but may not
- fully implement some edge cases (see `Deviations`_ below).
- Please report any issues encountered.
-
-.. seealso::
-
- * :doc:`passlib.hash.md5_crypt` (referred to as a "type 5" hash by Cisco)
- * :doc:`passlib.hash.cisco_pix`
+.. currentmodule:: passlib.hash
-Usage
-=====
+This class implements the "Type 7" password encoding used Cisco IOS.
+This is not actually a true hash, but a reversible XOR Cipher encoding of the plaintext
+password. Type 7 strings are (and were designed to be) plaintext equivalent;
+the goal was to protect from "over the shoulder" eavesdropping, and
+little else. They can be trivially decoded.
This class can be used directly as follows::
- >>> from passlib.hash import cisco_type7 as ct
+ >>> from passlib.hash import cisco_type7
>>> # encode password
- >>> h = ct.encrypt("password")
+ >>> h = cisco_type7.encrypt("password")
>>> h
'044B0A151C36435C0D'
- >>> #verify correct password
- >>> ct.verify("password", h)
+ >>> # verify password
+ >>> cisco_type7.verify("password", h)
True
- >>> #verify incorrect password
>>> pm.verify("letmein", h)
False
- >>> #check if hash is recognized
- >>> ct.identify(h)
- True
- >>> #check if some other hash is recognized
- >>> ct.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31')
- False
-
>>> # to demonstrate this is an encoding, not a real hash,
>>> # this class supports decoding the resulting string:
- >>> ct.decode(h)
+ >>> cisco_type7.decode(h)
"password"
+.. seealso:: :ref:`password hash usage <password-hash-examples>` for more examples
+
+.. note::
+
+ This implementation should work correctly for most cases, but may not
+ fully implement some edge cases (see `Deviations`_ below).
+ Please report any issues encountered.
+
Interface
=========
.. autoclass:: cisco_type7()
@@ -101,10 +93,10 @@ It may be updated as more information becomes available.
Type 7 encoding is primarily used with ``ASCII`` passwords,
how it handles other characters is not known.
- In order to provide support for unicode strings, PassLib will encode unicode
+ In order to provide support for unicode strings, Passlib will encode unicode
passwords using ``UTF-8`` before running them through this algorithm. If a
different encoding is desired by an application, the password should be
- encoded before handing it to PassLib.
+ encoded before handing it to Passlib.
* Magic Key:
diff --git a/docs/lib/passlib.hash.crypt16.rst b/docs/lib/passlib.hash.crypt16.rst
index 43f63c6..de9eff7 100644
--- a/docs/lib/passlib.hash.crypt16.rst
+++ b/docs/lib/passlib.hash.crypt16.rst
@@ -2,26 +2,19 @@
:class:`passlib.hash.crypt16` - Crypt16
=======================================================================
-.. currentmodule:: passlib.hash
-
-This class implements the Crypt16 password hash, commonly
-found on Ultrix and Tru64. It's a minor modification of :class:`~passlib.hash.des_crypt`,
-which allows passwords of up to 16 characters.
-
.. warning::
This algorithm is dangerously weak, and should not be used if at all possible.
-.. note::
+.. currentmodule:: passlib.hash
- This format is frequently confused with :class:`~passlib.hash.bigcrypt`,
- another derivative of des-crypt, because (for passwords between
- 9 and 16 chars in length) bigcrypt hashes will have
- the same size and character set.
+This class implements the Crypt16 password hash, commonly
+found on Ultrix and Tru64. It's a minor modification of :class:`~passlib.hash.des_crypt`,
+which allows passwords of up to 16 characters.
-Usage
-=====
-This class can be used in exactly the same manner as :class:`~passlib.hash.des_crypt`.
+.. seealso::
+ :ref:`password hash usage <password-hash-examples>` --
+ for examples of how to use this class via the common hash interface.
Interface
=========
@@ -40,6 +33,13 @@ A crypt16 hash string has the format :samp:`{salt}{checksum_1}{checksum_2}`, whe
:data:`hash64-big <passlib.utils.h64big>`-encoded 64-bit integer
(``X/UmCcBrceQ`` and ``0kQGGWKTbuE`` in the example).
+.. note::
+
+ This hash is frequently confused with the :doc:`bigcrypt <passlib.hash.bigcrypt>`
+ hash algorithm, as it has the same size and uses the same character
+ set as a :class:`!bigcrypt` hash of a password with 9 to 16
+ characters; though the actual algorithms are different.
+
.. rst-class:: html-toggle
Algorithm
@@ -110,10 +110,10 @@ This implementation of crypt16 deviates from public documentation of the format
(as evidenced by the fact that it discards the 8th bit of all password bytes).
In order to provide support for unicode strings,
- PassLib will encode unicode passwords using ``utf-8``
+ Passlib will encode unicode passwords using ``utf-8``
before running them through crypt16. If a different
encoding is desired by an application, the password should be encoded
- before handing it to PassLib.
+ before handing it to Passlib.
.. rubric:: Footnotes
diff --git a/docs/lib/passlib.hash.cta_pbkdf2_sha1.rst b/docs/lib/passlib.hash.cta_pbkdf2_sha1.rst
index 022d17c..f8136bc 100644
--- a/docs/lib/passlib.hash.cta_pbkdf2_sha1.rst
+++ b/docs/lib/passlib.hash.cta_pbkdf2_sha1.rst
@@ -13,24 +13,16 @@ variable length salts, variable number of rounds.
.. seealso::
- * :doc:`passlib.hash.pbkdf2_digest <passlib.hash.pbkdf2_digest>`
- for some other PBKDF2-based hashes.
+ * :ref:`password hash usage <password-hash-examples>` --
+ for examples of how to use this class via the common hash interface.
- * :doc:`passlib.hash.dlitz_pbkdf2_sha1 <passlib.hash.dlitz_pbkdf2_sha1>`
+ * :doc:`dlitz_pbkdf2_sha1 <passlib.hash.dlitz_pbkdf2_sha1>`
for another hash which looks almost exactly like this one.
-Usage
-=====
-This class support both rounds and salts,
-and can be used in the exact same manner
-as :doc:`SHA-512 Crypt <passlib.hash.sha512_crypt>`.
-
Interface
=========
.. autoclass:: cta_pbkdf2_sha1()
-.. rst-class:: html-toggle
-
Format & Algorithm
==================
diff --git a/docs/lib/passlib.hash.des_crypt.rst b/docs/lib/passlib.hash.des_crypt.rst
index 1c808c5..17113b3 100644
--- a/docs/lib/passlib.hash.des_crypt.rst
+++ b/docs/lib/passlib.hash.des_crypt.rst
@@ -2,40 +2,45 @@
:class:`passlib.hash.des_crypt` - DES Crypt
=======================================================================
-.. currentmodule:: passlib.hash
-
-This class implements the original DES-based Unix Crypt algorithm.
-While no longer in active use in most places,
-it is supported for legacy purposes by many Unix flavors.
-
.. warning::
This algorithm is extremely weak by modern standards,
and should not be used if possible.
-Usage
-=====
-This class can be used directly as follows::
+.. currentmodule:: passlib.hash
- >>> from passlib.hash import des_crypt as dc
+This class implements the original DES-based Unix Crypt algorithm.
+While no longer in active use in most places,
+it is supported for legacy purposes by many Unix flavors.
+It can used directly as follows::
+
+ >>> from passlib.hash import des_crypt
- >>> dc.encrypt("password") #generate new salt, encrypt password
+ >>> # generate new salt, encrypt password
+ >>> hash = des_crypt.encrypt("password")
'JQMuyS6H.AGMo'
- >>> dc.identify('JQMuyS6H.AGMo') #check if hash is recognized
+ >>> # verify the password
+ >>> des_crypt.verify("password", hash)
True
- >>> dc.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31') #check if some other hash is recognized
+ >>> des_crypt.verify("letmein", hash)
False
- >>> dc.verify("password", 'JQMuyS6H.AGMo') #verify correct password
- True
- >>> dc.verify("secret", 'JQMuyS6H.AGMo') #verify incorrect password
- False
+.. seealso:: :ref:`password hash usage <password-hash-examples>` for more examples
Interface
=========
.. autoclass:: des_crypt()
+.. note::
+
+ This class will use the first available of two possible backends:
+
+ * stdlib :func:`crypt()`, if the host OS supports DES-Crypt (most Unix systems).
+ * a pure Python implementation of DES-Crypt built into Passlib.
+
+ You can see which backend is in use by calling the :meth:`get_backend()` method.
+
Format
======
A des-crypt hash string consists of 13 characters, drawn from ``[./0-9A-Za-z]``.
@@ -109,7 +114,7 @@ This implementation of des-crypt differs from others in a few ways:
However, behavior in these cases varies wildly;
with implementations returning everything from errors
to incorrect hashes that never validate.
- To avoid all this, PassLib will throw an "invalid salt" if the provided
+ To avoid all this, Passlib will throw an "invalid salt" if the provided
salt string is not at least 2 characters.
* Restricted salt string character set:
@@ -119,7 +124,7 @@ This implementation of des-crypt differs from others in a few ways:
a 12-bit integer. Many implementations of des-crypt will
accept a salt containing other characters, but
vary wildly in how they are handled, including errors and implementation-specific value mappings.
- To avoid all this, PassLib will throw an "invalid salt" if the salt
+ To avoid all this, Passlib will throw an "invalid salt" if the salt
string contains any non-standard characters.
* Unicode Policy:
@@ -128,11 +133,12 @@ This implementation of des-crypt differs from others in a few ways:
(as evidenced by the fact that it discards the 8th bit of all password bytes).
In order to provide support for unicode strings,
- PassLib will encode unicode passwords using ``utf-8``
+ Passlib will encode unicode passwords using ``utf-8``
before running them through des-crypt. If a different
encoding is desired by an application, the password should be encoded
- before handing it to PassLib.
+ before handing it to Passlib.
.. rubric:: Footnotes
-.. [#] A java implementation of des-crypt, used as base for PassLib's pure-python implementation, is located at `<http://www.dynamic.net.au/christos/crypt/UnixCrypt2.txt>`_
+.. [#] A java implementation of des-crypt, used as base for Passlib's pure-python implementation,
+ can be found at `<http://www.dynamic.net.au/christos/crypt/UnixCrypt2.txt>`_
diff --git a/docs/lib/passlib.hash.django_std.rst b/docs/lib/passlib.hash.django_std.rst
index 1e4be54..a908f00 100644
--- a/docs/lib/passlib.hash.django_std.rst
+++ b/docs/lib/passlib.hash.django_std.rst
@@ -12,55 +12,126 @@ provides a module for storing user accounts and passwords
This module's password hashing code supports a few simple salted digests,
stored using the format :samp:`{id}${salt}${checksum}` (where :samp:`{id}`
is an identifier assigned by Django).
-Passlib provides support for all the hashes used by Django:
-
-* :class:`django_salted_sha1` - simple salted SHA1 digest, currently Django's default.
-* :class:`django_salted_md5` - simple salted MD5 digest.
-* :class:`django_des_crypt` - support for legacy :class:`des_crypt` hashes,
- shoehorned into Django's hash format.
-* :class:`hex_md5` - historical format used by old Django versions.
-
-.. warning::
-
- All of these hashes are suceptible to brute-force attacks;
- even the strongest of these (:class:`django_salted_sha1`)
- is a simple single-round salted digest.
- They should not be used for any purpose
- besides manipulating existing Django password hashes.
+Passlib provides support for all the hashes used up to and including
+Django 1.4
.. seealso::
- * :data:`passlib.apps.django_context` - a premade Django context
- which can read all of the formats listed below.
+ * :ref:`passlib.apps.django_context <django-contexts>` -
+ a set of premade contexts which mimic Django's builtin hashing policy,
+ and can read all of the formats listed below.
+..
* :mod:`passlib.ext.django` - a plugin that
updates Django to use a stronger hashing scheme,
and migrates existing hashes as users log in.
-Salted Hashes
-=============
+.. _django-1.4-hashes:
+
+Django 1.4 Hashes
+=================
+Django 1.4 introduced a new "hashers" framework, as well as
+three new modern large-salt variable-cost hash algorithms:
+
+* :class:`django_pbkdf2_sha256` - a PBKDF2-HMAC-SHA256 based hash.
+* :class:`django_pbkdf2_sha1` - a PBKDF2-HMAC-SHA1 based hash.
+* :class:`django_bcrypt` - a wrapper around :class:`~passlib.hash.bcrypt`.
-Usage
------
These classes can be used directly as follows::
- >>> from passlib.hash import django_salted_sha1 as dss
+ >>> from passlib.hash import django_pbkdf2_sha256 as handler
- >>> #encrypt password
- >>> h = dss.encrypt("password")
+ >>> # encrypt password
+ >>> h = handler.encrypt("password")
>>> h
- 'sha1$c6218$161d1ac8ab38979c5a31cbaba4a67378e7e60845'
+ 'pbkdf2_sha256$10000$s1w0UXDd00XB$+4ORmyvVWAQvoAEWlDgN34vlaJx1ZTZpa1pCSRey2Yk='
- >>> lms.identify(h) #check if hash is recognized
+ >>> # verify password
+ >>> handler.verify("password", h)
True
- >>> lms.identify('JQMuyS6H.AGMo') #check if some other hash is recognized
+ >>> handler.verify("eville", h)
False
- >>> lms.verify("password", h) #verify correct password
+.. seealso:: :ref:`password hash usage <password-hash-examples>` for more examples
+
+Interface
+---------
+
+.. autoclass:: django_pbkdf2_sha256()
+.. autoclass:: django_pbkdf2_sha1()
+.. data:: django_bcrypt()
+
+ This class implements Django 1.4's BCrypt wrapper, and follows the :ref:`password-hash-api`.
+
+ This is identical to :class:`!bcrypt` itself, but with
+ the Django-specific prefix ``"bcrypt$"`` prepended.
+ See :doc:`/lib/passlib.hash.bcrypt` for more details,
+ the usage and behavior is identical.
+
+ This should be compatible with the hashes generated by
+ Django 1.4's :class:`!BCryptPasswordHasher` class.
+
+ .. versionadded:: 1.6
+
+Format
+------
+An example :class:`!django_pbkdf2_sha256` hash (of ``password``) is:
+
+ ``pbkdf2_sha256$10000$s1w0UXDd00XB$+4ORmyvVWAQvoAEWlDgN34vlaJx1ZTZpa1pCSRey2Yk=``
+
+Both of Django's PBKDF2 hashes have the same basic format,
+:samp:`{ident}${rounds}${salt}${checksum}`, where:
+
+* :samp:`{ident}` is an identifier (``pbkdf2_sha256`` in the case of the example).
+
+* :samp:`{rounds}` is a variable cost parameter encoded in decimal.
+
+* :samp:`{salt}` consists of (usually 12) alphanumeric digits
+ (``s1w0UXDd00XB`` in the example).
+
+* :samp:`{checksum}` is the base64 encoding the PBKDF2 digest.
+
+The digest porition is generated by passing the ``utf-8`` encoded password,
+the ``ascii``-encoded salt string, and the number of rounds into
+PBKDF2 using the HMAC-SHA256 prf; and generated a 32 byte checksum,
+which is then encoding using base64.
+
+The other PBKDF2 wrapper functions similarly.
+
+Django 1.0 Hashes
+=================
+.. warning::
+
+ All of the following hashes are very susceptible to brute-force attacks;
+ since they are simple single-round salted digests.
+ They should not be used for any purpose
+ besides manipulating existing Django password hashes.
+
+Django 1.0 supports some basic salted digests, as well as some
+legacy hashes:
+
+* :class:`django_salted_sha1` - simple salted SHA1 digest, Django 1.0-1.3's default.
+* :class:`django_salted_md5` - simple salted MD5 digest.
+* :class:`django_des_crypt` - support for legacy :class:`des_crypt` hashes,
+ shoehorned into Django's hash format.
+
+These classes can be used directly as follows::
+
+ >>> from passlib.hash import django_salted_sha1 as handler
+
+ >>> # encrypt password
+ >>> h = handler.encrypt("password")
+ >>> h
+ 'sha1$c6218$161d1ac8ab38979c5a31cbaba4a67378e7e60845'
+
+ >>> # verify password
+ >>> handler.verify("password", h)
True
- >>> lms.verify("secret", h) #verify incorrect password
+ >>> handler.verify("eville", h)
False
+.. seealso:: :ref:`password hash usage <password-hash-examples>` for more examples
+
Interface
---------
@@ -103,8 +174,8 @@ Django's salted hashes should not be considered very secure.
increasing the odds that a particular salt+password string
will be present in a pre-computed tables of ascii digests.
-Des Crypt
-=========
+Des Crypt Wrapper
+=================
.. autoclass:: django_des_crypt()
@@ -132,10 +203,11 @@ see :class:`des_crypt`.
Other Hashes
============
-.. autoclass:: django_disabled
+.. autoclass:: django_disabled()
.. note::
- Older versions of Django may also have
- passwords encoded using :class:`~passlib.hash.hex_md5`,
- though this has been deprecated by Django.
+ Some older (pre-1.0) versions of Django encoded
+ passwords using :class:`~passlib.hash.hex_md5`,
+ though this has been deprecated by Django,
+ and should become increasingly rare.
diff --git a/docs/lib/passlib.hash.dlitz_pbkdf2_sha1.rst b/docs/lib/passlib.hash.dlitz_pbkdf2_sha1.rst
index 04e7acb..b55ef05 100644
--- a/docs/lib/passlib.hash.dlitz_pbkdf2_sha1.rst
+++ b/docs/lib/passlib.hash.dlitz_pbkdf2_sha1.rst
@@ -13,24 +13,16 @@ variable length salts, variable number of rounds.
.. seealso::
- * :doc:`passlib.hash.pbkdf2_digest <passlib.hash.pbkdf2_digest>`
- for some other PBKDF2-based hashes.
+ * :ref:`password hash usage <password-hash-examples>` --
+ for examples of how to use this class via the common hash interface.
- * :doc:`passlib.hash.cta_pbkdf2_sha1 <passlib.hash.cta_pbkdf2_sha1>`
+ * :doc:`cta_pbkdf2_sha1 <passlib.hash.cta_pbkdf2_sha1>`
for another hash which looks almost exactly like this one.
-Usage
-=====
-This class support both rounds and salts,
-and can be used in the exact same manner
-as :doc:`SHA-512 Crypt <passlib.hash.sha512_crypt>`.
-
Interface
=========
.. autoclass:: dlitz_pbkdf2_sha1()
-.. rst-class:: html-toggle
-
Format & Algorithm
==================
diff --git a/docs/lib/passlib.hash.fshp.rst b/docs/lib/passlib.hash.fshp.rst
index 54de676..60e490d 100644
--- a/docs/lib/passlib.hash.fshp.rst
+++ b/docs/lib/passlib.hash.fshp.rst
@@ -4,50 +4,42 @@
.. index:: fshp
-.. currentmodule:: passlib.hash
-
-The Fairly Secure Hashed Password (FSHP) scheme [#home]_
-is a cross-platform hash based on PBKDF1 [#pbk]_, and uses an LDAP-style hash format.
-It features a variable length salt, variable rounds, and support for cryptographic
-hashes from SHA-1 up to SHA-512.
-
-.. warning::
+.. note::
While the SHA-2 variants of PBKDF1 have no critical security vulnerabilities,
PBKDF1 itself has been deprecated in favor of it's successor, PBKDF2.
Furthermore, FSHP has been listed as insecure by it's author (for unspecified reasons);
so this scheme should probably only be used to support existing hashes.
-Usage
-=====
-This class supports the standard passlib options for rounds and salt,
-as well as a special digest keyword for selecting the variant of FSHP to use.
+.. currentmodule:: passlib.hash
-This class can be used directly as follows::
+The Fairly Secure Hashed Password (FSHP) scheme [#home]_
+is a cross-platform hash based on PBKDF1 [#pbk]_, and uses an LDAP-style hash format.
+It features a variable length salt, variable rounds, and support for cryptographic
+hashes from SHA-1 up to SHA-512.
+This class supports the standard Passlib options for rounds and salt,
+as well as a special digest keyword for selecting the variant of FSHP to use.
+It can be used directly as follows::
>>> from passlib.hash import fshp
- >>> #generate new salt, encrypt password
- >>> h = fshp.encrypt("password")
- >>> h
+ >>> # generate new salt, encrypt password
+ >>> hash = fshp.encrypt("password")
+ >>> hash
'{FSHP1|16|16384}PtoqcGUetmVEy/uR8715TNqKa8+teMF9qZO1lA9lJNUm1EQBLPZ+qPRLeEPHqy6C'
- >>> #same, but with explict number of rounds, larger salt, and specific variant
+ >>> # the same, but with an explicit number of rounds, larger salt, and specific variant
>>> fshp.encrypt("password", rounds=40000, salt_size=32, variant="sha512")
- '{FSHP3|32|40000}cB8yE/CuADSgUTQZjWy+YTf/cvbU11D/rHNKiUiB6z4dIaO77U/rmNWpgZcZllZbCra5GJ8ZfFRNwCHirPqvYTAnbaQQeFQbWym/frRrRev3buoygFQRYexl4091Pc5m'
+ '{FSHP3|32|40000}cB8yE/CuADSgUTQZjWy+YTf/cvbU11D/rHNKiUiB6z4dIaO77U/rmNW
+ pgZcZllZbCra5GJ8ZfFRNwCHirPqvYTAnbaQQeFQbWym/frRrRev3buoygFQRYexl4091Pc5m'
- >>> #check if hash is recognized
- >>> fshp.identify(h)
+ >>> # verify password
+ >>> fshp.verify("password", hash)
True
- >>> #check if some other hash is recognized
- >>> fshp.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31')
+ >>> fshp.verify("secret", hash)
False
- >>> #verify correct password
- >>> fshp.verify("password", h)
- True
- >>> fshp.verify("secret", h) #verify incorrect password
- False
+.. seealso:: :ref:`password hash usage <password-hash-examples>` for more examples
Interface
=========
@@ -117,10 +109,10 @@ Deviations
as well as all known reference hashes.
In order to provide support for unicode strings,
- PassLib will encode unicode passwords using ``utf-8``
+ Passlib will encode unicode passwords using ``utf-8``
before running them through FSHP. If a different
encoding is desired by an application, the password should be encoded
- before handing it to PassLib.
+ before handing it to Passlib.
.. rubric:: Footnotes
diff --git a/docs/lib/passlib.hash.grub_pbkdf2_sha512.rst b/docs/lib/passlib.hash.grub_pbkdf2_sha512.rst
index c781ecf..5f82597 100644
--- a/docs/lib/passlib.hash.grub_pbkdf2_sha512.rst
+++ b/docs/lib/passlib.hash.grub_pbkdf2_sha512.rst
@@ -15,14 +15,11 @@ variable length salts, variable number of rounds.
.. seealso::
- * :doc:`passlib.hash.pbkdf2_digest <passlib.hash.pbkdf2_digest>`
- for some other PBKDF2-based hashes.
+ * :ref:`password hash usage <password-hash-examples>` --
+ for examples of how to use this class via the common hash interface.
-Usage
-=====
-These classes support both rounds and salts,
-and can be used in the exact same manner
-as :doc:`SHA-512 Crypt <passlib.hash.sha512_crypt>`.
+ * :doc:`passlib.hash.pbkdf2_{digest} <passlib.hash.pbkdf2_digest>` --
+ for some other PBKDF2-based hashes.
Interface
=========
diff --git a/docs/lib/passlib.hash.hex_digests.rst b/docs/lib/passlib.hash.hex_digests.rst
index 8b3100f..e1a7aa0 100644
--- a/docs/lib/passlib.hash.hex_digests.rst
+++ b/docs/lib/passlib.hash.hex_digests.rst
@@ -2,54 +2,51 @@
:samp:`passlib.hash.hex_{digest}` - Generic Hexdecimal Digests
==============================================================
-.. currentmodule:: passlib.hash
-
-Some existing applications store passwords by storing them using
-hexidecimal-encoded message digests, such as MD5 or SHA1.
-Such schemes are *extremely* vulnerable to pre-computed brute-force attacks,
-and should not be used in new applications. However, for the sake
-of backwards compatibility when converting existing applications,
-PassLib provides wrappers for few of the common hashes.
-
.. warning::
- To reiterate the above:
Using a single round of any cryptographic hash
(especially without a salt) is so insecure
that it's barely better than plaintext.
Do not use these schemes in new applications.
+.. currentmodule:: passlib.hash
-Usage
-=====
+Some existing applications store passwords by storing them using
+hexidecimal-encoded message digests, such as MD5 or SHA1.
+Such schemes are *extremely* vulnerable to pre-computed brute-force attacks,
+and should not be used in new applications. However, for the sake
+of backwards compatibility when converting existing applications,
+Passlib provides wrappers for few of the common hashes.
These classes all wrap the underlying hashlib implementations,
-and are mainly useful only for plugging them into a :class:`~passlib.context.CryptContext`.
-However, they can be used directly as follows::
+and can be used directly as follows::
- >>> from passlib.hash import hex_sha1 as hs
+ >>> from passlib.hash import hex_sha1 as hex_sha1
>>> #encrypt password
- >>> h = hs.encrypt("password")
+ >>> h = hex_sha1.encrypt("password")
>>> h
'5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8'
- >>> hs.identify(h) #check if hash is recognized
+ >>> hex_sha1.verify("password", h) #verify correct password
True
- >>> hs.identify('JQMuyS6H.AGMo') #check if some other hash is recognized
+ >>> hex_sha1.verify("secret", h) #verify incorrect password
False
- >>> hs.verify("password", h) #verify correct password
- True
- >>> hs.verify("secret", h) #verify incorrect password
- False
+.. seealso:: :ref:`password hash usage <password-hash-examples>` for more examples
Interface
=========
-.. autoclass:: hex_md4()
-.. autoclass:: hex_md5()
-.. autoclass:: hex_sha1()
-.. autoclass:: hex_sha256()
-.. autoclass:: hex_sha512()
+.. class:: hex_md4()
+.. class:: hex_md5()
+.. class:: hex_sha1()
+.. class:: hex_sha256()
+.. class:: hex_sha512()
+
+ Each of these classes implements a plain hexidecimal encoded
+ message digest, using the relevant digest function from :mod:`!hashlib`,
+ and following the :ref:`password-hash-api`.
+
+ They support no settings or other keywords.
Format & Algorithm
==================
diff --git a/docs/lib/passlib.hash.ldap_crypt.rst b/docs/lib/passlib.hash.ldap_crypt.rst
index cded54a..2ba7e33 100644
--- a/docs/lib/passlib.hash.ldap_crypt.rst
+++ b/docs/lib/passlib.hash.ldap_crypt.rst
@@ -1,6 +1,6 @@
-===========================================================
+================================================================
:samp:`passlib.hash.ldap_{crypt}` - LDAP crypt() Wrappers
-===========================================================
+================================================================
.. currentmodule:: passlib.hash
@@ -10,41 +10,40 @@ One of these, identified by RFC 2307 as the ``{CRYPT}`` scheme,
is somewhat different from the others.
Instead of specifying a password hashing scheme,
it's supposed to wrap the host OS's :func:`!crypt()`.
-
Being host-dependant, the actual hashes supported
by this scheme may differ greatly between host systems.
In order to provide uniform support across platforms,
-Passlib defines a corresponding :samp:`ldap_{xxx}_crypt` scheme
+Passlib defines a corresponding :samp:`ldap_{crypt-scheme}` class
for each of the :ref:`standard unix hashes <standard-unix-hashes>`.
+These classes all wrap the underlying implementations documented
+elsewhere in Passlib, and can be used directly as follows::
-.. seealso::
+ >>> from passlib.hash import ldap_md5_crypt
- * :doc:`passlib.hash.ldap_std` - the other standard LDAP hashes.
+ >>> # encrypt password
+ >>> hash = ldap_md5_crypt.encrypt("password")
+ >>> hash
+ '{CRYPT}$1$gwvn5BO0$3dyk8j.UTcsNUPrLMsU6/0'
- * :mod:`!passlib.apps` for a :ref:`list of premade ldap contexts <ldap-contexts>`.
+ >>> # verify password
+ >>> ldap_md5_crypt.verify("password", hash)
+ True
+ >>> ldap_md5_crypt.verify("secret", hash)
+ False
-Usage
-=====
-These classes all wrap the underlying implementations,
-and are mainly useful only for plugging them into a :class:`~passlib.context.CryptContext`.
-However, they can be used directly as follows::
+ >>> # determine if the underlying crypt() algorithm is supported
+ >>> # by your host OS, or if the builtin Passlib implementation is being used.
+ >>> # "os_crypt" - host supported; "builtin" - passlib version
+ >>> ldap_md5_crypt.get_backend()
+ "os_crypt"
- >>> from passlib.hash import ldap_md5_crypt as lmc
+.. seealso::
- >>> #encrypt password
- >>> h = lmc.encrypt("password")
- >>> h
- '{CRYPT}$1$gwvn5BO0$3dyk8j.UTcsNUPrLMsU6/0'
+ * :ref:`password hash usage <password-hash-examples>` -- for more usage examples
- >>> lmc.identify(h) #check if hash is recognized
- True
- >>> lmc.identify('JQMuyS6H.AGMo') #check if some other hash is recognized
- False
+ * :doc:`ldap_{digest} <passlib.hash.ldap_std>` -- for the other standard LDAP hashes.
- >>> lmc.verify("password", h) #verify correct password
- True
- >>> lmc.verify("secret", h) #verify incorrect password
- False
+ * :mod:`passlib.apps` -- for a list of :ref:`premade ldap contexts <ldap-contexts>`.
Interface
=========
@@ -59,12 +58,6 @@ Interface
All of these classes have the same interface as their corresponding
underlying hash (eg :class:`des_crypt`, :class:`md5_crypt`, etc).
-.. note::
-
- In order to determine if a particular hash is actually supported
- natively by your host OS, use an test such as
- ``ldap_des_crypt.has_backend("os_crypt")`` or similar.
-
.. rubric:: Footnotes
.. [#pwd] The manpage for :command:`slappasswd` - `<http://gd.tuwien.ac.at/linuxcommand.org/man_pages/slappasswd8.html>`_.
diff --git a/docs/lib/passlib.hash.ldap_other.rst b/docs/lib/passlib.hash.ldap_other.rst
index abbd900..75007f1 100644
--- a/docs/lib/passlib.hash.ldap_other.rst
+++ b/docs/lib/passlib.hash.ldap_other.rst
@@ -10,7 +10,10 @@ but are not part of any standard.
.. seealso::
- :ref:`ldap-hashes` for a full list of RFC 2307 style hashes.
+ * :ref:`password hash usage <password-hash-examples>` --
+ for examples of how to use these classes via the common hash interface.
+
+ * :ref:`ldap-hashes` for a full list of RFC 2307 style hashes.
Hexidecimal Digests
===================
diff --git a/docs/lib/passlib.hash.ldap_pbkdf2_digest.rst b/docs/lib/passlib.hash.ldap_pbkdf2_digest.rst
index 822f8a9..909bce9 100644
--- a/docs/lib/passlib.hash.ldap_pbkdf2_digest.rst
+++ b/docs/lib/passlib.hash.ldap_pbkdf2_digest.rst
@@ -6,7 +6,7 @@
.. currentmodule:: passlib.hash
-PassLib provides three custom hash schemes based on the PBKDF2 [#pbkdf2]_ algorithm
+Passlib provides three custom hash schemes based on the PBKDF2 [#pbkdf2]_ algorithm
which are compatible with the :ref:`ldap hash format <ldap-hashes>`:
:class:`!ldap_pbkdf2_sha1`, :class:`!ldap_pbkdf2_sha256`, :class:`!ldap_pbkdf2_sha512`.
They feature variable length salts, variable rounds.
diff --git a/docs/lib/passlib.hash.ldap_std.rst b/docs/lib/passlib.hash.ldap_std.rst
index 9418335..0b0b13a 100644
--- a/docs/lib/passlib.hash.ldap_std.rst
+++ b/docs/lib/passlib.hash.ldap_std.rst
@@ -9,42 +9,30 @@ LDAP hash formats specified by :rfc:`2307`.
This includes ``{MD5}``, ``{SMD5}``, ``{SHA}``, ``{SSHA}``.
These schemes range from somewhat to very insecure,
and should not be used except when required.
-
-.. note::
-
- RFC 2307 also specifies a ``{CRYPT}`` scheme,
- which is supposed to wrap the host OS's :func:`!crypt()`.
- Being host-dependant, this scheme is somewhat different,
- and is details in :doc:`passlib.hash.ldap_crypt`.
-
-.. seealso::
-
- * :doc:`passlib.hash.ldap_crypt`
-
- * :mod:`!passlib.apps` for a :ref:`list of premade ldap contexts <ldap-contexts>`.
-
-Usage
-=====
These classes all wrap the underlying hashlib implementations,
-and are mainly useful only for plugging them into a :class:`~passlib.context.CryptContext`.
-However, they can be used directly as follows::
+and are can be used directly as follows::
>>> from passlib.hash import ldap_salted_md5 as lsm
- >>> #encrypt password
- >>> h = lsm.encrypt("password")
- >>> h
+ >>> # encrypt password
+ >>> hash = lsm.encrypt("password")
+ >>> hash
'{SMD5}OqsUXNHIhHbznxrqHoIM+ZT8DmE='
- >>> lms.identify(h) #check if hash is recognized
+ >>> # verify password
+ >>> lms.verify("password", hash)
True
- >>> lms.identify('JQMuyS6H.AGMo') #check if some other hash is recognized
+ >>> lms.verify("secret", hash)
False
- >>> lms.verify("password", h) #verify correct password
- True
- >>> lms.verify("secret", h) #verify incorrect password
- False
+.. seealso::
+
+ * :ref:`password hash usage <password-hash-examples>` -- for more usage examples
+
+ * :doc:`ldap_{crypt} <passlib.hash.ldap_crypt>` --
+ LDAP ``{CRYPT}`` wrappers for common Unix hash algorithms.
+
+ * :mod:`passlib.apps` -- for a list of :ref:`premade ldap contexts <ldap-contexts>`.
Plain Hashes
============
@@ -62,7 +50,7 @@ Format
These hashes have the format :samp:`{prefix}{checksum}`.
-* :samp:`{prefix}` is `{MD5}` for ldap_md5, and `{SHA}` for ldap_sha1.
+* :samp:`{prefix}` is ``{MD5}`` for ldap_md5, and ``{SHA}`` for ldap_sha1.
* :samp:`{checksum}` is the base64 encoding
of the raw message digest of the password,
using the appropriate digest algorithm.
@@ -77,8 +65,8 @@ Salted Hashes
These hashes have the format :samp:`{prefix}{data}`.
-* :samp:`{prefix}` is `{SMD5}` for ldap_salted_md5,
- and `{SSHA}` for ldap_salted_sha1.
+* :samp:`{prefix}` is ``{SMD5}`` for ldap_salted_md5,
+ and ``{SSHA}`` for ldap_salted_sha1.
* :samp:`{data}` is the base64 encoding of :samp:`{checksum}{salt}`;
and in turn :samp:`{salt}` is a multi-byte binary salt,
and :samp:`{checksum}` is the raw digest of the
@@ -122,7 +110,7 @@ Deviations
* The salt size for the salted digests appears to vary between applications.
While OpenLDAP is fixed at 4 bytes, some systems appear to use 8 or more.
- Passlib can accept and generate strings with salts between 4-16 bytes,
+ As of 1.6, Passlib can accept and generate strings with salts between 4-16 bytes,
though various servers may differ in what they can handle.
.. rubric:: Footnotes
diff --git a/docs/lib/passlib.hash.lmhash.rst b/docs/lib/passlib.hash.lmhash.rst
index a2c3774..fdd3234 100644
--- a/docs/lib/passlib.hash.lmhash.rst
+++ b/docs/lib/passlib.hash.lmhash.rst
@@ -4,6 +4,14 @@
:class:`passlib.hash.lmhash` - LanManager Hash
==================================================================
+.. versionadded:: 1.6
+
+.. warning::
+
+ 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.
+
.. currentmodule:: passlib.hash
This class implements the LanManager Hash (aka *LanMan* or *LM* hash).
@@ -12,15 +20,6 @@ until it was supplanted (though not entirely replaced) by
the :doc:`nthash <passlib.hash.nthash>` algorithm in Windows NT.
It continues to crop up in production due to it's integral role
in the legacy NTLM authentication protocol.
-
-.. warning::
-
- 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.
-
-Usage
-=====
This class can be used directly as follows::
>>> from passlib.hash import lmhash
@@ -37,12 +36,11 @@ This class can be used directly as follows::
>>> lmhash.verify("secret", h)
False
- >>> # check if hash is recognized
- >>> lmhash.identify(h)
- True
- >>> # check if some other hash is recognized
- >>> lmhash.identify('3azHgidD$SrJPt7B.9rekpmwJwtON31')
- False
+.. seealso:: :ref:`password hash usage <password-hash-examples>` for more examples
+
+Interface
+=========
+.. autoclass:: lmhash()
Issues with Non-ASCII Characters
--------------------------------
@@ -53,11 +51,7 @@ the same way. While Passlib makes every attempt to behave as close to correct
as possible, the meaning of "correct" is dependant on the software you are
interoperating with. If you think you will have passwords containing
non-``ascii`` characters, please read the `Deviations`_ section (below) for
-details about the known interoperability issues.
-
-Interface
-=========
-.. autoclass:: lmhash
+details about the known interoperability issues. It's a mess of codepages.
.. rst-class:: html-toggle
diff --git a/docs/lib/passlib.hash.md5_crypt.rst b/docs/lib/passlib.hash.md5_crypt.rst
index 6305e8f..5796cd5 100644
--- a/docs/lib/passlib.hash.md5_crypt.rst
+++ b/docs/lib/passlib.hash.md5_crypt.rst
@@ -15,44 +15,48 @@ and most unix flavors have since replaced with with stronger schemes,
such as :class:`~passlib.hash.sha512_crypt` and :class:`~passlib.hash.bcrypt`.
This is also referred to under Cisco IOS systems as a "type 5" hash.
-The format and algorithm are identical, though Cisco seems to require [#cisco]_
+The format and algorithm are identical, though Cisco seems to require
4 salt characters instead of the full 8 characters
-used by most systems.
+used by most systems [#cisco]_.
-Usage
-=====
-PassLib provides an md5_crypt class, which can be can be used directly as follows::
+The :class:`!md5_crypt` class can be can be used directly as follows::
>>> from passlib.hash import md5_crypt
- >>> #generate new salt, encrypt password
+ >>> # generate new salt, encrypt password
>>> h = md5_crypt.encrypt("password")
>>> h
'$1$3azHgidD$SrJPt7B.9rekpmwJwtON31'
-
- >>> #verify correct password
+ >>> # verify the password
>>> md5_crypt.verify("password", h)
True
- >>> #verify incorrect password
>>> md5_crypt.verify("secret", h)
False
- >>> #check if hash is recognized
- >>> md5_crypt.identify(h)
- True
- >>> #check if some other hash is recognized
- >>> md5_crypt.identify('JQMuyS6H.AGMo')
- False
-
>>> # encrypt password using cisco-compatible 4-char salt
>>> md5_crypt.encrypt("password", salt_size=4)
'$1$wu98$9UuD3hvrwehnqyF1D548N0'
+.. seealso::
+
+ * :ref:`password hash usage <password-hash-examples>` -- for more usage examples
+
+ * :doc:`apr_md5_crypt <passlib.hash.apr_md5_crypt>` -- Apache's variant of this algorithm.
+
Interface
=========
.. autoclass:: md5_crypt()
+.. note::
+
+ This class will use the first available of two possible backends:
+
+ * stdlib :func:`crypt()`, if the host OS supports MD5-Crypt (most Unix systems).
+ * a pure python implementation of MD5-Crypt built into Passlib.
+
+ You can see which backend is in use by calling the :meth:`get_backend()` method.
+
Format
======
An example md5-crypt hash (of the string ``password``) is ``$1$5pZSV9va$azfrPr6af3Fc7dLblQXVa0``.
@@ -162,13 +166,13 @@ though it is not yet considered broken:
Deviations
==========
-PassLib's implementation of md5-crypt differs from the reference implementation (and others) in two ways:
+Passlib's implementation of md5-crypt differs from the reference implementation (and others) in two ways:
* Restricted salt string character set:
The underlying algorithm can unambigously handle salt strings
which contain any possible byte value besides ``\x00`` and ``$``.
- However, PassLib strictly limits salts to the
+ However, Passlib strictly limits salts to the
:data:`hash64 <passlib.utils.HASH64_CHARS>` character set,
as nearly all implementations of md5-crypt generate
and expect salts containing those characters,
@@ -183,10 +187,10 @@ PassLib's implementation of md5-crypt differs from the reference implementation
as well as all known reference hashes.
In order to provide support for unicode strings,
- PassLib will encode unicode passwords using ``utf-8``
+ Passlib will encode unicode passwords using ``utf-8``
before running them through md5-crypt. If a different
encoding is desired by an application, the password should be encoded
- before handing it to PassLib.
+ before handing it to Passlib.
.. rubric:: Footnotes
diff --git a/docs/lib/passlib.hash.msdcc.rst b/docs/lib/passlib.hash.msdcc.rst
index 737952d..864bd46 100644
--- a/docs/lib/passlib.hash.msdcc.rst
+++ b/docs/lib/passlib.hash.msdcc.rst
@@ -4,6 +4,13 @@
:class:`passlib.hash.msdcc` - Windows' Domain Cached Credentials
======================================================================
+.. versionadded:: 1.6
+
+.. warning::
+
+ This hash is not very secure, and should mainly be used to verify
+ existing cached credentials.
+
.. currentmodule:: passlib.hash
This class implements the DCC (Domain Cached Credentials) hash, used
@@ -13,43 +20,30 @@ including "mscache" and "mscash" (Microsoft CAched haSH). Security wise
it is not particularly strong, as it's little more than :doc:`nthash <passlib.hash.nthash>`
salted with a username. It was replaced by :doc:`msdcc2 <passlib.hash.msdcc2>`
in Windows Vista.
-
-.. warning::
-
- This hash is not very secure, and should mainly be used to verify
- existing cached credentials.
-
-.. seealso::
-
- :doc:`passlib.hash.msdcc2`
-
-Usage
-=====
This class can be used directly as follows::
>>> from passlib.hash import msdcc
>>> # encrypt password using specified username
- >>> h = msdcc.encrypt("password", "Administrator")
- >>> h
+ >>> hash = msdcc.encrypt("password", user="Administrator")
+ >>> hash
'25fd08fa89795ed54207e6e8442a6ca0'
- >>> #verify correct password
- >>> msdcc.verify("password", h, "Administrator")
+ >>> # verify correct password
+ >>> msdcc.verify("password", hash, user="Administrator")
True
- >>> #verify correct password w/ wrong username
- >>> msdcc.verify("password", h, "User")
+ >>> # verify correct password w/ wrong username
+ >>> msdcc.verify("password", hash, user="User")
False
- >>> #verify incorrect password
- >>> msdcc.verify("letmein", h, "Administrator")
+ >>> # verify incorrect password
+ >>> msdcc.verify("letmein", hash, user="Administrator")
False
- >>> # check if hash may belong to msdcc
- >>> msdcc.identify(h)
- True
- >>> # check if foreign hash belongs to msdcc
- >>> msdcc.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31')
- False
+.. seealso::
+
+ * :ref:`password hash usage <password-hash-examples>` -- for more usage examples
+
+ * :doc:`msdcc2 <passlib.hash.msdcc2>` -- the successor to this hash
Interface
=========
diff --git a/docs/lib/passlib.hash.msdcc2.rst b/docs/lib/passlib.hash.msdcc2.rst
index 3ff41e6..016cf81 100644
--- a/docs/lib/passlib.hash.msdcc2.rst
+++ b/docs/lib/passlib.hash.msdcc2.rst
@@ -4,6 +4,8 @@
:class:`passlib.hash.msdcc2` - Windows' Domain Cached Credentials v2
======================================================================
+.. versionadded:: 1.6
+
.. currentmodule:: passlib.hash
This class implements the DCC2 (Domain Cached Credentials version 2) hash, used
@@ -14,34 +16,30 @@ the weaker :doc:`msdcc (v1)<passlib.hash.msdcc>` hash used by previous releases
of Windows. Security wise it is not particularly weak, but due to it's
use of the username as a salt, it should probably not be used for anything
but verifying existing cached credentials.
-
-Usage
-=====
This class can be used directly as follows::
>>> from passlib.hash import msdcc2
>>> # encrypt password using specified username
- >>> h = msdcc2.encrypt("password", "Administrator")
- >>> h
+ >>> hash = msdcc2.encrypt("password", user="Administrator")
+ >>> hash
'4c253e4b65c007a8cd683ea57bc43c76'
- >>> #verify correct password
- >>> msdcc2.verify("password", h, "Administrator")
+ >>> # verify correct password
+ >>> msdcc2.verify("password", hash, user="Administrator")
True
- >>> #verify correct password w/ wrong username
- >>> msdcc2.verify("password", h, "User")
+ >>> # verify correct password w/ wrong username
+ >>> msdcc2.verify("password", hash, user="User")
False
- >>> #verify incorrect password
- >>> msdcc2.verify("letmein", h, "Administrator")
+ >>> # verify incorrect password
+ >>> msdcc2.verify("letmein", hash, user="Administrator")
False
- >>> # check if hash may belong to msdcc
- >>> msdcc2.identify(h)
- True
- >>> # check if foreign hash belongs to msdcc
- >>> msdcc2.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31')
- False
+.. seealso::
+
+ * :ref:`password hash usage <password-hash-examples>` -- for more usage examples
+
+ * :doc:`msdcc <passlib.hash.msdcc>` -- the predecessor to this hash
Interface
=========
diff --git a/docs/lib/passlib.hash.mssql2000.rst b/docs/lib/passlib.hash.mssql2000.rst
index 5c079f5..84a285f 100644
--- a/docs/lib/passlib.hash.mssql2000.rst
+++ b/docs/lib/passlib.hash.mssql2000.rst
@@ -2,43 +2,39 @@
:class:`passlib.hash.mssql2000` - MS SQL 2000 password hash
==================================================================
-.. currentmodule:: passlib.hash
-
-This class implements the hash algorithm used by Microsoft SQL Server 2000
-to store it's user account passwords, until it was replaced
-by a slightly more secure variant (:class:`~passlib.hash.mssql2005`)
-in MSSQL 2005.
+.. versionadded:: 1.6
.. warning::
This hash is not very secure, and should not be used for any purposes
besides manipulating existing MSSQL 2000 password hashes.
-.. seealso::
-
- :class:`~passlib.hash.mssql2005`
+.. currentmodule:: passlib.hash
-Usage
-=====
-This class can be used directly as follows (note that this class requires
-a username for all encrypt/verify operations)::
+This class implements the hash algorithm used by Microsoft SQL Server 2000
+to store it's user account passwords, until it was replaced
+by a slightly more secure variant (:class:`~passlib.hash.mssql2005`)
+in MSSQL 2005.
+This class can be used directly as follows::
>>> from passlib.hash import mssql2000 as m20
- >>> #encrypt password using specified username
+ >>> # encrypt password
>>> h = m20.encrypt("password")
>>> h
'0x0100200420C4988140FD3920894C3EDC188E94F428D57DAD5905F6CC1CBAF950CAD4C63F272B2C91E4DEEB5E6444'
- >>> m20.identify(h) #check if hash is recognized
+ >>> # verify correct password
+ >>> m20.verify("password", h)
True
- >>> m20.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31') #check if some other hash is recognized
+ >>> m20.verify("letmein", h)
False
- >>> m20.verify("password", h) #verify correct password
- True
- >>> m20.verify("letmein", h) #verify incorrect password
- False
+.. seealso::
+
+ * :ref:`password hash usage <password-hash-examples>` -- for more usage examples
+
+ * :doc:`mssql2005 <passlib.hash.mssql2005>` -- the successor to this hash.
Interface
=========
diff --git a/docs/lib/passlib.hash.mssql2005.rst b/docs/lib/passlib.hash.mssql2005.rst
index 9a3728d..f74b04e 100644
--- a/docs/lib/passlib.hash.mssql2005.rst
+++ b/docs/lib/passlib.hash.mssql2005.rst
@@ -2,42 +2,38 @@
:class:`passlib.hash.mssql2005` - MS SQL 2005 password hash
==================================================================
-.. currentmodule:: passlib.hash
-
-This class implements the hash algorithm used by Microsoft SQL Server 2005
-to store it's user account passwords, replacing the slightly less secure
-:class:`~passlib.hash.mssql2000` variant.
+.. versionadded:: 1.6
.. warning::
This hash is not very secure, and should not be used for any purposes
besides manipulating existing MSSQL 2005 password hashes.
-.. seealso::
-
- :class:`~passlib.hash.mssql2000`
+.. currentmodule:: passlib.hash
-Usage
-=====
-This class can be used directly as follows (note that this class requires
-a username for all encrypt/verify operations)::
+This class implements the hash algorithm used by Microsoft SQL Server 2005
+to store it's user account passwords, replacing the slightly less secure
+:class:`~passlib.hash.mssql2000` variant.
+This class can be used directly as follows::
>>> from passlib.hash import mssql2005 as m25
- >>> #encrypt password using specified username
+ >>> # encrypt password
>>> h = m25.encrypt("password")
>>> h
'0x01006ACDF9FF5D2E211B392EEF1175EFFE13B3A368CE2F94038B'
- >>> m25.identify(h) #check if hash is recognized
+ >>> # verify password
+ >>> m25.verify("password", h)
True
- >>> m25.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31') #check if some other hash is recognized
+ >>> m25.verify("letmein", h)
False
- >>> m25.verify("password", h) #verify correct password
- True
- >>> m25.verify("letmein", h) #verify incorrect password
- False
+.. seealso::
+
+ * :ref:`password hash usage <password-hash-examples>` -- for more usage examples
+
+ * :doc:`mssql2000 <passlib.hash.mssql2000>` -- the predecessor to this hash.
Interface
=========
diff --git a/docs/lib/passlib.hash.mysql323.rst b/docs/lib/passlib.hash.mysql323.rst
index 144c4ae..eda604d 100644
--- a/docs/lib/passlib.hash.mysql323.rst
+++ b/docs/lib/passlib.hash.mysql323.rst
@@ -6,43 +6,38 @@
.. currentmodule:: passlib.hash
-
-This class implements the first of MySQL's password hash functions,
-used to store it's user account passwords. Introduced in MySQL 3.2.3
-under the function ``PASSWORD()``, this function was renamed
-to ``OLD_PASSWORD()`` under MySQL 4.1, when a newer password
-hash algorithm was introduced (see :class:`~passlib.hash.mysql41`).
-
.. warning::
This algorithm is extremely weak, and should not be used
for any purposes besides manipulating existing Mysql 3.2.3-4.0
password hashes.
-.. seealso::
-
- :mod:`!passlib.apps` for a list of predefined :ref:`mysql contexts <mysql-contexts>`.
-
-Usage
-=====
+This class implements the first of MySQL's password hash functions,
+used to store it's user account passwords. Introduced in MySQL 3.2.3
+under the function ``PASSWORD()``, this function was renamed
+to ``OLD_PASSWORD()`` under MySQL 4.1, when a newer password
+hash algorithm was introduced (see :class:`~passlib.hash.mysql41`).
Users will most likely find the frontends provided by :mod:`passlib.apps`
to be more useful than accessing this class directly.
That aside, this class can be used as follows::
- >>> from passlib.hash import mysql323 as mold
+ >>> from passlib.hash import mysql323
- >>> mold.encrypt("password") #encrypt password
+ >>> # encrypt password
+ >>> mysql323.encrypt("password")
'5d2e19393cc5ef67'
- >>> mold.identify('5d2e19393cc5ef67') #check if hash is recognized
+ >>> #verify correct password
+ >>> mysql323.verify("password", '5d2e19393cc5ef67')
True
- >>> mold.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31') #check if another type of hash is recognized
+ >>> mysql323.verify("secret", '5d2e19393cc5ef67')
False
- >>> mold.verify("password", '5d2e19393cc5ef67') #verify correct password
- True
- >>> mold.verify("secret", '5d2e19393cc5ef67') #verify incorrect password
- False
+.. seealso::
+
+ * :ref:`password hash usage <password-hash-examples>` -- for more usage examples
+
+ * :mod:`passlib.apps` -- for a list of predefined :ref:`mysql contexts <mysql-contexts>`.
Interface
=========
@@ -52,8 +47,8 @@ Format & Algorithm
==================
A mysql-323 password hash consists of 16 hexidecimal digits,
directly encoding the 64 bit checksum. MySQL always uses
-lower-case letters, and so does PassLib
-(though PassLib will recognize upper case letters as well).
+lower-case letters, and so does Passlib
+(though Passlib will recognize upper case letters as well).
The algorithm used is extremely simplistic, for details,
see the source implementation in the footnotes [#f1]_.
diff --git a/docs/lib/passlib.hash.mysql41.rst b/docs/lib/passlib.hash.mysql41.rst
index ad1b7cf..4b9c0db 100644
--- a/docs/lib/passlib.hash.mysql41.rst
+++ b/docs/lib/passlib.hash.mysql41.rst
@@ -6,28 +6,26 @@
.. currentmodule:: passlib.hash
-This class implements the second of MySQL's password hash functions,
-used to store it's user account passwords. Introduced in MySQL 4.1.1
-under the function ``PASSWORD()``, it replaced the previous
-algorithm (:class:`~passlib.hash.mysql323`) as the default
-used by MySQL, and is still in active use under MySQL 5.
-
.. warning::
This algorithm is extremely weak, and should not be used
for any purposes besides manipulating existing Mysql 4.1+
password hashes.
+This class implements the second of MySQL's password hash functions,
+used to store it's user account passwords. Introduced in MySQL 4.1.1
+under the function ``PASSWORD()``, it replaced the previous
+algorithm (:class:`~passlib.hash.mysql323`) as the default
+used by MySQL, and is still in active use under MySQL 5.
+Users will most likely find the frontends provided by :mod:`passlib.apps`
+to be more useful than accessing this class directly.
+
.. seealso::
- :mod:`!passlib.apps` for a :ref:`list of premade mysql contexts <mysql-contexts>`.
+ * :ref:`password hash usage <password-hash-examples>` --
+ for examples of how to use this class via the common hash interface.
-Usage
-=====
-Users will most likely find the frontends provided by :mod:`passlib.apps`
-to be more useful than accessing this class directly.
-That aside, this class can be used in the same manner
-as :class:`~passlib.hash.mysql323`.
+ * :mod:`passlib.apps` for a list of :ref:`premade mysql contexts <mysql-contexts>`.
Interface
=========
@@ -39,7 +37,7 @@ A mysql-41 password hash consists of an asterisk ``*`` followed
by 40 hexidecimal digits, directly encoding the 160 bit checksum.
An example hash (of ``password``) is ``*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19``.
MySQL always uses upper-case letters,
-and so does PassLib (though PassLib will recognize lower-case letters as well).
+and so does Passlib (though Passlib will recognize lower-case letters as well).
The checksum is calculated simply, as the SHA1 hash of the SHA1 hash of the password,
which is then encoded into hexidecimal.
diff --git a/docs/lib/passlib.hash.nthash.rst b/docs/lib/passlib.hash.nthash.rst
index d0c4811..1c92baf 100644
--- a/docs/lib/passlib.hash.nthash.rst
+++ b/docs/lib/passlib.hash.nthash.rst
@@ -4,11 +4,7 @@
:class:`passlib.hash.nthash` - Windows' NT-HASH
==================================================================
-.. currentmodule:: passlib.hash
-
-This class implements the NT-HASH algorithm, used by Microsoft Windows NT
-and successors to store user account passwords, supplanting
-the much weaker :doc:`lmhash <passlib.hash.lmhash>` algorithm.
+.. versionadded:: 1.6
.. warning::
@@ -17,34 +13,31 @@ the much weaker :doc:`lmhash <passlib.hash.lmhash>` algorithm.
It should be used for compatibility with existing systems;
**do not use** in new code.
-Usage
-=====
+.. currentmodule:: passlib.hash
+
+This class implements the NT-HASH algorithm, used by Microsoft Windows NT
+and successors to store user account passwords, supplanting
+the much weaker :doc:`lmhash <passlib.hash.lmhash>` algorithm.
This class can be used directly as follows::
>>> from passlib.hash import nthash
- >>> #encrypt password
+ >>> # encrypt password
>>> h = nthash.encrypt("password")
>>> h
'8846f7eaee8fb117ad06bdd830b7586c'
- >>> #check if hash is recognized
- >>> nthash.identify(h)
- True
- >>> #check if some other hash is recognized
- >>> nthash.identify('3azHgidD$SrJPt7B.9rekpmwJwtON31')
- False
-
- >>> #verify correct password
+ >>> # verify password
>>> nthash.verify("password", h)
True
- >>> #verify incorrect password
>>> nthash.verify("secret", h)
False
+.. seealso:: :ref:`password hash usage <password-hash-examples>` for more examples
+
Interface
=========
-.. autoclass:: nthash
+.. autoclass:: nthash()
Format & Algorithm
==================
@@ -73,7 +66,10 @@ NTHASH digest. An example digest (of ``password``) is
It has no salt and a single fixed round.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept no optional keywords.
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept no optional keywords.
+
+ .. versionchanged:: 1.6
+ This hash was named ``nthash`` under previous releases of Passlib.
Security Issues
===============
diff --git a/docs/lib/passlib.hash.oracle10.rst b/docs/lib/passlib.hash.oracle10.rst
index 2ef4124..7fd6ccb 100644
--- a/docs/lib/passlib.hash.oracle10.rst
+++ b/docs/lib/passlib.hash.oracle10.rst
@@ -4,46 +4,42 @@
.. currentmodule:: passlib.hash
-This class implements the hash algorithm used by the Oracle Database up to
-version 10g Rel.2. It was superceded by a newer algorithm in :class:`Oracle 11 <passlib.hash.oracle11>`.
-
.. warning::
This hash is not secure, and should not be used for any purposes
besides manipulating existing Oracle 10 password hashes.
-.. warning::
-
- This implementation has not been compared
- very carefully against the official implementation or reference documentation,
- and it's behavior may not match under various border cases.
- It should not be relied on for anything but novelty purposes
- for the time being.
-
-Usage
-=====
+This class implements the hash algorithm used by the Oracle Database up to
+version 10g Rel.2. It was superceded by a newer algorithm in :class:`Oracle 11 <passlib.hash.oracle11>`.
This class can be used directly as follows (note that this class requires
a username for all encrypt/verify operations)::
- >>> from passlib.hash import oracle10 as or10
+ >>> from passlib.hash import oracle10 as oracle10
>>> #encrypt password using specified username
- >>> h = or10.encrypt("password", "username")
- >>> h
+ >>> hash = oracle10.encrypt("password", user="username")
+ >>> hash
'872805F3F4C83365'
- >>> or10.identify(h) #check if hash is recognized
+ >>> #verify correct password
+ >>> oracle10.verify("password", hash, user="username")
True
- >>> or10.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31') #check if some other hash is recognized
+ >>> #verify correct password w/ wrong username
+ >>> oracle10.verify("password", hash, user="somebody")
False
-
- >>> or10.verify("password", h, "username") #verify correct password
- True
- >>> or10.verify("password", h, "somebody") #verify correct password w/ wrong username
- False
- >>> or10.verify("letmein", h, "username") #verify incorrect password
+ >>> #verify incorrect password
+ >>> oracle10.verify("letmein", hash, user="username")
False
+.. seealso:: :ref:`password hash usage <password-hash-examples>` for more examples
+
+.. warning::
+
+ This implementation has not been compared
+ very carefully against the official implementation or reference documentation,
+ and it's behavior may not match under various border cases.
+ *caveat emptor*.
+
Interface
=========
.. autoclass:: oracle10()
@@ -91,7 +87,7 @@ Oracle10 account passwords, due to the following flaws [#flaws]_:
Deviations
==========
-PassLib's implementation of the Oracle10g hash may deviate from the official
+Passlib's implementation of the Oracle10g hash may deviate from the official
implementation in unknown ways, as there is no official documentation.
There is only one known issue:
@@ -100,7 +96,7 @@ There is only one known issue:
Lack of testing (and test vectors) leaves it unclear
as to how Oracle 10g handles passwords containing non-7bit ascii.
In order to provide support for unicode strings,
- PassLib will encode unicode passwords using ``utf-16-be`` [#enc]_
+ Passlib will encode unicode passwords using ``utf-16-be`` [#enc]_
before running them through the Oracle10g algorithm.
This behavior may be altered in the future, if further testing
reveals another behavior is more in line with the official representation.
@@ -110,7 +106,7 @@ There is only one known issue:
.. rubric:: Footnotes
.. [#enc] The exact encoding used in step 3 of the algorithm is not clear from known references.
- PassLib uses ``utf-16-be``, as this is both compatible with existing test vectors,
+ Passlib uses ``utf-16-be``, as this is both compatible with existing test vectors,
and supports unicode input.
.. [#flaws] Whitepaper analyzing flaws in this algorithm -
diff --git a/docs/lib/passlib.hash.oracle11.rst b/docs/lib/passlib.hash.oracle11.rst
index 9f5ea02..84282d2 100644
--- a/docs/lib/passlib.hash.oracle11.rst
+++ b/docs/lib/passlib.hash.oracle11.rst
@@ -6,35 +6,29 @@
This class implements the hash algorithm introduced in version 11g of the Oracle Database.
It supercedes the :class:`Oracle 10 <passlib.hash.oracle10>` password hash.
+This class can be can be used directly as follows::
-.. warning::
-
- This implementation has not been compared
- very carefully against the official implementation or reference documentation,
- and it's behavior may not match under various border cases.
- It should not be relied on for anything but novelty purposes
- for the time being.
-
-Usage
-=====
-PassLib provides an oracle11 class, which can be can be used directly as follows::
-
- >>> from passlib.hash import oracle11 as or11
+ >>> from passlib.hash import oracle11 as oracle11
>>> #generate new salt, encrypt password
- >>> h = or11.encrypt("password")
- >>> h
+ >>> hash = oracle11.encrypt("password")
+ >>> hash
'S:4143053633E59B4992A8EA17D2FF542C9EDEB335C886EED9C80450C1B4E6'
- >>> or11.identify(h) #check if hash is recognized
+ >>> # verify password
+ >>> oracle11.verify("password", hash)
True
- >>> or11.identify('JQMuyS6H.AGMo') #check if some other hash is recognized
+ >>> oracle11.verify("secret", hash)
False
- >>> or11.verify("password", h) #verify correct password
- True
- >>> or11.verify("secret", h) #verify incorrect password
- False
+.. seealso:: :ref:`password hash usage <password-hash-examples>` for more examples
+
+.. warning::
+
+ This implementation has not been compared
+ very carefully against the official implementation or reference documentation,
+ and it's behavior may not match under various border cases.
+ *caveat emptor*.
Interface
=========
@@ -64,7 +58,7 @@ of :samp:`{password}{raw_salt}` is then encoded into hexidecimal, and returned a
Deviations
==========
-PassLib's implementation of the Oracle11g hash may deviate from the official
+Passlib's implementation of the Oracle11g hash may deviate from the official
implementation in unknown ways, as there is no official documentation.
There is only one known issue:
@@ -73,7 +67,7 @@ There is only one known issue:
Lack of testing (and test vectors) leaves it unclear
as to how Oracle 11g handles passwords containing non-7bit ascii.
In order to provide support for unicode strings,
- PassLib will encode unicode passwords using ``utf-8``
+ Passlib will encode unicode passwords using ``utf-8``
before running them through Oracle11.
This behavior may be altered in the future, if further testing
reveals another behavior is more in line with the official representation.
diff --git a/docs/lib/passlib.hash.pbkdf2_digest.rst b/docs/lib/passlib.hash.pbkdf2_digest.rst
index a4830c1..b48f719 100644
--- a/docs/lib/passlib.hash.pbkdf2_digest.rst
+++ b/docs/lib/passlib.hash.pbkdf2_digest.rst
@@ -6,10 +6,12 @@
.. currentmodule:: passlib.hash
-PassLib provides three custom hash schemes based on the PBKDF2 [#pbkdf2]_ algorithm
+Passlib provides three custom hash schemes based on the PBKDF2 [#pbkdf2]_ algorithm
which are compatible with the :ref:`modular crypt format <modular-crypt-format>`:
-:class:`!pbkdf2_sha1`, :class:`!pbkdf2_sha256`, :class:`!pbkdf2_sha512`.
-They feature variable length salts, variable rounds.
+
+* :class:`pbkdf2_sha1`
+* :class:`pbkdf2_sha256`
+* :class:`pbkdf2_sha512`
Security-wise, PBKDF2 is currently one of the leading key derivation functions,
and has no known security issues.
@@ -20,52 +22,45 @@ versions are offered as well.
PBKDF2-SHA512 is one of the three hashes Passlib
:ref:`recommends <recommended-hashes>` for new applications.
-.. seealso::
-
- Alternate version of these hashes - :doc:`LDAP-Compatible Simple PBKDF2 Hashes <passlib.hash.ldap_pbkdf2_digest>`
-
-Usage
-=====
-All of the following classes can be used directly as follows::
+All of these classes can be used directly as follows::
- >>> from passlib.hash import pbkdf2_sha256 as engine
+ >>> from passlib.hash import pbkdf2_sha256
- >>> #generate new salt, encrypt password
- >>> hash = engine.encrypt("password")
+ >>> # generate new salt, encrypt password
+ >>> hash = pbkdf2_sha256.encrypt("password")
>>> hash
'$pbkdf2-sha256$6400$0ZrzXitFSGltTQnBWOsdAw$Y11AchqV4b0sUisdZd0Xr97KWoymNE0LNNrnEgY4H9M'
- >>> #same, but with explicit number of rounds and salt length
- >>> engine.encrypt("password", rounds=8000, salt_size=10)
+ >>> # same, but with an explicit number of rounds and salt length
+ >>> pbkdf2_sha256.encrypt("password", rounds=8000, salt_size=10)
'$pbkdf2-sha256$8000$XAuBMIYQQogxRg$tRRlz8hYn63B9LYiCd6PRo6FMiunY9ozmMMI3srxeRE'
- >>> #check if hash is a pbkdf2-sha256 hash
- >>> engine.identify(hash)
+ >>> # verify the password
+ >>> pbkdf2_sha256.verify("password", hash)
True
- >>> #check if some other hash is recognized
- >>> engine.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31')
+ >>> pbkdf2_sha256.verify("wrong", hash)
False
- >>> #verify correct password
- >>> engine.verify("password", hash)
- True
- >>> #verify incorrect password
- >>> engine.verify("wrong", hash)
- False
+.. seealso::
+
+ * :ref:`password hash usage <password-hash-examples>` -- for more usage examples
+
+ * :doc:`ldap_pbkdf2_{digest} <passlib.hash.ldap_pbkdf2_digest>` --
+ alternate LDAP-compatible versions of these hashes.
Interface
=========
-.. class:: pbkdf2_sha1()
+.. autoclass:: pbkdf2_sha256()
+
+.. class:: pbkdf2_sha512()
except for the choice of message digest,
- this class is the same as :class:`pbkdf2_sha512`.
+ this class is the same as :class:`pbkdf2_sha256`.
-.. class:: pbkdf2_sha256()
+.. class:: pbkdf2_sha1()
except for the choice of message digest,
- this class is the same as :class:`pbkdf2_sha512`.
-
-.. autoclass:: pbkdf2_sha512()
+ this class is the same as :class:`pbkdf2_sha256`.
.. _mcf-pbkdf2-format:
diff --git a/docs/lib/passlib.hash.phpass.rst b/docs/lib/passlib.hash.phpass.rst
index ee5c036..17c357b 100644
--- a/docs/lib/passlib.hash.phpass.rst
+++ b/docs/lib/passlib.hash.phpass.rst
@@ -7,17 +7,16 @@
.. currentmodule:: passlib.hash
This algorithm is used primarily by PHP software
-which uses PHPass [#home],
-a PHP library similar to PassLib. The PHPass Portable Hash
+which uses PHPass [#pp]_,
+a PHP library similar to Passlib. The PHPass Portable Hash
is a custom password hash used by PHPass as a fallback
when none of it's other hashes are available.
Due to it's reliance on MD5, and the simplistic implementation,
other hash algorithms should be used if possible.
-Usage
-=====
-Supporting a variable sized salt and variable number of rounds,
-this scheme is used in exactly the same way as :doc:`bcrypt <passlib.hash.bcrypt>`.
+.. seealso::
+ :ref:`password hash usage <password-hash-examples>` --
+ for examples of how to use this class via the common hash interface.
Interface
=========
@@ -66,10 +65,10 @@ This implementation of phpass differs from the specification in one way:
is implied by nearly all known reference hashes.
In order to provide support for unicode strings,
- PassLib will encode unicode passwords using ``utf-8``
+ Passlib will encode unicode passwords using ``utf-8``
before running them through phpass. If a different
encoding is desired by an application, the password should be encoded
- before handing it to PassLib.
+ before handing it to Passlib.
.. rubric:: Footnotes
diff --git a/docs/lib/passlib.hash.plaintext.rst b/docs/lib/passlib.hash.plaintext.rst
index 5d51ac1..2b1fb91 100644
--- a/docs/lib/passlib.hash.plaintext.rst
+++ b/docs/lib/passlib.hash.plaintext.rst
@@ -4,37 +4,31 @@
.. currentmodule:: passlib.hash
-This class stores passwords in plaintext.
-This is, of course, ridiculously insecure;
+This class stores passwords in plaintext. This is, of course, ridiculously insecure;
it is provided for backwards compatibility when migrating
existing applications. *It should not be used* for any other purpose.
-
-.. seealso::
-
- * :class:`passlib.hash.ldap_plaintext` is probably more appropriate
- to use in conjunction with other LDAP style hashes.
-
-Usage
-=====
-This class is mainly useful only for plugging into a :class:`~passlib.context.CryptContext`.
-When used, it should always be the last scheme in the list,
-as it will recognize all hashes.
+This class should always be the last algorithm checked, as it will recognize all hashes.
It can be used directly as follows::
- >>> from passlib.hash import plaintext as pt
+ >>> from passlib.hash import plaintext as plaintext
- >>> #"encrypt" password
- >>> pt.encrypt("password")
+ >>> # "encrypt" password
+ >>> plaintext.encrypt("password")
'password'
- >>> nt.identify('password') #check if hash is recognized (all hashes are recognized)
- True
-
- >>> nt.verify("password", "password") #verify correct password
+ >>> # verify password
+ >>> plaintext.verify("password", "password")
True
- >>> nt.verify("secret", "password") #verify incorrect password
+ >>> plaintext.verify("secret", "password")
False
+.. seealso::
+
+ * :ref:`password hash usage <password-hash-examples>` -- for more usage examples
+
+ * :class:`ldap_plaintext <passlib.hash.ldap_plaintext>` -- on LDAP systems,
+ this format is probably more appropriate for storing plaintext passwords.
+
Interface
=========
-.. autoclass:: plaintext
+.. autoclass:: plaintext()
diff --git a/docs/lib/passlib.hash.postgres_md5.rst b/docs/lib/passlib.hash.postgres_md5.rst
index 6bafbed..2d038ef 100644
--- a/docs/lib/passlib.hash.postgres_md5.rst
+++ b/docs/lib/passlib.hash.postgres_md5.rst
@@ -4,42 +4,39 @@
:class:`passlib.hash.postgres_md5` - PostgreSQL MD5 password hash
==================================================================
-.. currentmodule:: passlib.hash
-
-This class implements the md5-based hash algorithm used by PostgreSQL to store
-it's user account passwords. This scheme was introduced in PostgreSQL 7.2;
-prior to this PostgreSQL stored it's password in plain text.
-
.. warning::
This hash is not secure, and should not be used for any purposes
besides manipulating existing PostgreSQL password hashes.
-Usage
-=====
+.. currentmodule:: passlib.hash
+
+This class implements the md5-based hash algorithm used by PostgreSQL to store
+it's user account passwords. This scheme was introduced in PostgreSQL 7.2;
+prior to this PostgreSQL stored it's password in plain text.
Users will most likely find the frontend provided by :mod:`passlib.apps`
to be more useful than accessing this class directly.
That aside, this class can be used directly as follows::
- >>> from passlib.hash import postgres_md5 as pm
+ >>> from passlib.hash import postgres_md5
- >>> #encrypt password using specified username
- >>> h = pm.encrypt("password", "username")
- >>> h
+ >>> # encrypt password using specified username
+ >>> hash = postgres_md5.encrypt("password", user="username")
+ >>> hash
'md55a231fcdb710d73268c4f44283487ba2'
- >>> pm.identify(h) #check if hash is recognized
+ >>> # verify correct password
+ >>> postgres_md5.verify("password", hash, user="username")
True
- >>> pm.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31') #check if some other hash is recognized
+ >>> # verify correct password w/ wrong username
+ >>> postgres_md5.verify("password", hash, user="somebody")
False
-
- >>> pm.verify("password", h, "username") #verify correct password
- True
- >>> pm.verify("password", h, "somebody") #verify correct password w/ wrong username
- False
- >>> pm.verify("password", h, "username") #verify incorrect password
+ >>> # verify incorrect password
+ >>> postgres_md5.verify("password", hash, user="username")
False
+.. seealso:: :ref:`password hash usage <password-hash-examples>` for more examples
+
Interface
=========
.. autoclass:: postgres_md5()
diff --git a/docs/lib/passlib.hash.rst b/docs/lib/passlib.hash.rst
index 1dda3b9..43e9da1 100644
--- a/docs/lib/passlib.hash.rst
+++ b/docs/lib/passlib.hash.rst
@@ -3,37 +3,71 @@
==============================================
.. module:: passlib.hash
- :synopsis: all password hashes provided by PassLib
+ :synopsis: all password hashes provided by Passlib
Overview
========
-The :mod:`!passlib.hash` module contains all the password hashes built into Passlib.
-Each object within this package implements a different password hashing scheme,
-but all have the same uniform interface. The hashes in this module can used in two ways:
+The :mod:`!passlib.hash` module contains all the password hash algorithms built into Passlib.
+While each hash has it's own options and output format, they all share a common interface,
+documented in detail in the :ref:`password-hash-api`. The following pages
+first describe the common interface, and then each hash in detail (
+it's including format, algorithm, and known security issues).
+
+.. seealso:: :doc:`Quickstart Guide </new_app_quickstart>` -- advice on
+ choosing an appropriately secure hash for your new application.
+
+Usage
+=====
+All of the hashes in this module can used in two ways:
+
+1. They can be imported 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 - encrypt() takes care of salt generation, unicode encoding, etc.
+ >>> hash = md5_crypt.encrypt("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 :doc:`CryptContext <passlib.context>` 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.encrypt("password")
+ >>> hash1
+ '$1$2y72Yi12$o6Yu2OyjN.9FiK.9HJ7i5.'
+ >>> hash2 = pwd_context.encrypt("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
+
+For additional details, usage examples, and full documentation of all
+methods and attributes provided by the common hash interface:
-They can be imported and used directly, as in the following example::
-
- >>> from passlib.hash import md5_crypt
- >>> md5_crypt.encrypt("password")
- '$1$IU54yC7Y$nI1wF8ltcRvaRHwMIjiJq1'
-
-More commonly, they can be referenced by name
-when constructing a custom :doc:`CryptContext <passlib.context>` object,
-as in the following example::
-
- >>> from passlib.context import CryptContext
- >>> #note below that md5_crypt and des_crypt are both names of classes in passlib.hash
- >>> pwd_context = CryptContext(["md5_crypt", "des_crypt"])
- >>> pwd_context.encrypt("password")
- '$1$2y72Yi12$o6Yu2OyjN.9FiK.9HJ7i5.'
-
-.. seealso::
-
- * :ref:`password-hash-api` -- details the
- interface used by all password hashes in this module.
+.. toctree::
+ :maxdepth: 2
- * :doc:`Quickstart Guide </new_app_quickstart>` --
- for advice on choosing an appropriately secure hash for your new application.
+ /password_hash_api
.. _mcf-hashes:
@@ -115,6 +149,9 @@ All of the following hashes use a variant of the password hash format
used by LDAPv2. Originally specified in :rfc:`2307` and used by OpenLDAP [#openldap]_,
the basic format ``{SCHEME}HASH`` has seen widespread adoption in a number of programs.
+.. [#openldap] OpenLDAP homepage - `<http://www.openldap.org/>`_.
+
+
.. _standard-ldap-hashes:
Standard LDAP Schemes
@@ -163,8 +200,8 @@ but follow the LDAP format:
.. _database-hashes:
-Database Hashes
-===============
+SQL Database Hashes
+===================
The following schemes are used by various SQL databases
to encode their own user accounts.
These schemes have encoding and contextual requirements
@@ -181,10 +218,10 @@ not seen outside those specific contexts:
passlib.hash.oracle10
passlib.hash.oracle11
-.. _other-hashes:
+.. _windows-hashes:
-Windows Hashes
-==============
+MS Windows Hashes
+=================
The following hashes are used in various places by Microsoft Windows.
As they were designed for "internal" use, they generally contain
no identifying markers, identifying them is pretty much context-dependant.
@@ -197,6 +234,8 @@ no identifying markers, identifying them is pretty much context-dependant.
passlib.hash.msdcc
passlib.hash.msdcc2
+.. _other-hashes:
+
Other Hashes
============
The following schemes are used in various contexts,
@@ -218,7 +257,3 @@ in one of the above categories:
passlib.hash.grub_pbkdf2_sha512
passlib.hash.hex_digests
passlib.hash.plaintext
-
-.. rubric:: Footnotes
-
-.. [#openldap] OpenLDAP homepage - `<http://www.openldap.org/>`_.
diff --git a/docs/lib/passlib.hash.scram.rst b/docs/lib/passlib.hash.scram.rst
index 3625c39..9a232a4 100644
--- a/docs/lib/passlib.hash.scram.rst
+++ b/docs/lib/passlib.hash.scram.rst
@@ -4,6 +4,8 @@
:class:`passlib.hash.scram` - SCRAM Hash
===================================================================
+.. versionadded:: 1.6
+
.. currentmodule:: passlib.hash
SCRAM is a password-based challenge response protocol defined by :rfc:`5802`.
@@ -34,63 +36,55 @@ This class can be used like any other Passlib hash, as follows::
>>> from passlib.hash import scram
- >>> #generate new salt, encrypt password against default list of algorithms
- >>> h = scram.encrypt("password")
- >>> h # (output split over multiple lines for readability)
- '$scram$6400$.Z/znnNOKWUsBaCU$sha-1=cRseQyJpnuPGn3e6d6u6JdJWk.0,sha-256=5G\
- cjEbRaUIIci1r6NAMdI9OPZbxl9S5CFR6la9CHXYc,sha-512=.DHbIm82ajXbFR196Y.9Ttbs\
+ >>> # generate new salt, encrypt password against default list of algorithms
+ >>> hash = scram.encrypt("password")
+ >>> hash
+ '$scram$6400$.Z/znnNOKWUsBaCU$sha-1=cRseQyJpnuPGn3e6d6u6JdJWk.0,sha-256=5G
+ cjEbRaUIIci1r6NAMdI9OPZbxl9S5CFR6la9CHXYc,sha-512=.DHbIm82ajXbFR196Y.9Ttbs
gzvGjbMeuWCtKve8TPjRMNoZK9EGyHQ6y0lW9OtWdHZrDZbBUhB9ou./VI2mlw'
- >>> #same, but with explict number of rounds
+ >>> # same, but with an explicit number of rounds
>>> scram.encrypt("password", rounds=8000)
- '$scram$8000$Y0zp/R/DeO89h/De$sha-1=eE8dq1f1P1hZm21lfzsr3CMbiEA,sha-256=Nf\
- kaDFMzn/yHr/HTv7KEFZqaONo6psRu5LBBFLEbZ.o,sha-512=XnGG11X.J2VGSG1qTbkR3FVr\
+ '$scram$8000$Y0zp/R/DeO89h/De$sha-1=eE8dq1f1P1hZm21lfzsr3CMbiEA,sha-256=Nf
+ kaDFMzn/yHr/HTv7KEFZqaONo6psRu5LBBFLEbZ.o,sha-512=XnGG11X.J2VGSG1qTbkR3FVr
9j5JwsnV5Fd094uuC.GtVDE087m8e7rGoiVEgXnduL48B2fPsUD9grBjURjkiA'
- >>> #check if hash is recognized
- >>> scram.identify(h)
- True
- >>> #check if some other hash is recognized
- >>> scram.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31')
- False
-
- >>> #verify correct password
- >>> scram.verify("password", h)
+ >>> # verify password
+ >>> scram.verify("password", hash)
True
- >>> scram.verify("secret", h) #verify incorrect password
+ >>> scram.verify("secret", hash)
False
-Additionally, this class provides a number of useful methods
-for SCRAM-specific actions::
+See :ref:`password hash usage <password-hash-examples>` for more examples
+for more examples of how to use the common hash interface.
+Additionally, this class provides a number of useful methods for SCRAM-specific actions:
- >>> from passlib.hash import scram
- >>> # generate new salt, encrypt password against default list of algorithms
- >>> scram.encrypt("password")
- '$scram$6400$.Z/znnNOKWUsBaCU$sha-1=cRseQyJpnuPGn3e6d6u6JdJWk.0,sha-256=5G\
- cjEbRaUIIci1r6NAMdI9OPZbxl9S5CFR6la9CHXYc,sha-512=.DHbIm82ajXbFR196Y.9Ttbs\
- gzvGjbMeuWCtKve8TPjRMNoZK9EGyHQ6y0lW9OtWdHZrDZbBUhB9ou./VI2mlw'
+* You can override the default list of digests, and/or the number of iterations::
- >>> # generate new salt, encrypt password against specific list of algorithms
- >>> # and choose explicit number of rounds
- >>> h = scram.encrypt("password", rounds=1000, algs="sha-1,sha-256,md5")
- >>> h
- '$scram$1000$RsgZo7T2/l8rBUBI$md5=iKsH555d3ctn795Za4S7bQ,sha-1=dRcE2AUjALLF\
+ >>> hash = scram.encrypt("password", rounds=1000, algs="sha-1,sha-256,md5")
+ >>> hash
+ '$scram$1000$RsgZo7T2/l8rBUBI$md5=iKsH555d3ctn795Za4S7bQ,sha-1=dRcE2AUjALLF
tX5DstdLCXZ9Afw,sha-256=WYE/LF7OntriUUdFXIrYE19OY2yL0N5qsQmdPNFn7JE'
- >>> # given a scram hash, retrieve the information SCRAM needs
- >>> # to authenticate using a specific mechanism -
- >>> # returns salt, rounds, digest
- >>> scram.extact_digest_info(h, "sha-1")
+* Given a scram hash, you can use a single call to extract all the information
+ the SCRAM needs to authenticate against a specific mechanism::
+
+ >>> # this returns (salt_bytes, rounds, digest_bytes)
+ >>> scram.extact_digest_info(hash, "sha-1")
('F\xc8\x19\xa3\xb4\xf6\xfe_+\x05@H',
1000,
'u\x17\x04\xd8\x05#\x00\xb2\xc5\xb5~C\xb2\xd7K\tv}\x01\xfc')
- >>> # given a scram hash, return list of digest algs present
- >>> scram.extract_digest_algs(h)
+* Given a scram hash, you can extract the list of digest algorithms
+ it contains information for (``sha-1`` will always be present)::
+
+ >>> scram.extract_digest_algs(hash)
["md5", "sha-1", "sha-256"]
- >>> # and a standalone helper that can calculate the SaltedPassword
- >>> # portion of the SCRAM protocol, taking care of SASLPrep as well.
+* This class also provides a standalone helper which can calculate
+ the ``SaltedPassword`` portion of the SCRAM protocol, taking
+ care of the SASLPrep step as well::
+
>>> scram.derive_digest("password", b'\x01\x02\x03', 1000, "sha-1")
b'k\x086vg\xb3\xfciz\xb4\xb4\xe2JRZ\xaet\xe4`\xe7'
@@ -113,7 +107,7 @@ An example scram hash (of the string ``password``) is::
cjEbRaUIIci1r6NAMdI9OPZbxl9S5CFR6la9CHXYc,sha-512=.DHbIm82ajXbFR196Y.9Ttb
sgzvGjbMeuWCtKve8TPjRMNoZK9EGyHQ6y0lW9OtWdHZrDZbBUhB9ou./VI2mlw
-An scram hash string has the format :samp:`$scram${rounds}${salt}${alg1}={digest1},{alg2}={digest2},{...}`, where:
+An scram hash string has the format :samp:`$scram${rounds}${salt}${alg1}={digest1},{alg2}={digest2},...`, where:
* ``$scram$`` is the prefix used to identify Passlib scram hashes,
following the :ref:`modular-crypt-format`
@@ -134,9 +128,11 @@ An scram hash string has the format :samp:`$scram${rounds}${salt}${alg1}={digest
* There will always be one or more :samp:`{alg}={digest}` pairs, separated by a
comma. Per the SCRAM specification, the algorithm ``sha-1`` should always be present.
-There is also an alternate format (:samp:`$scram${rounds}${salt}${alg}{,...}`)
+There is also an alternate format (:samp:`$scram${rounds}${salt}${alg},...`)
which is used to represent a configuration string that doesn't contain
-any digests. An example would be ``$scram$6400$.Z/znnNOKWUsBaCU$sha-1,sha-256,sha-512``.
+any digests. An example would be::
+
+ $scram$6400$.Z/znnNOKWUsBaCU$sha-1,sha-256,sha-512
The algorithm used to calculate each digest is::
diff --git a/docs/lib/passlib.hash.sha1_crypt.rst b/docs/lib/passlib.hash.sha1_crypt.rst
index 639429d..9c184f8 100644
--- a/docs/lib/passlib.hash.sha1_crypt.rst
+++ b/docs/lib/passlib.hash.sha1_crypt.rst
@@ -8,15 +8,23 @@ SHA1-Crypt is a hash algorithm introduced by NetBSD in 2004.
It's based on a variation of the PBKDF1 algorithm,
and supports a large salt and variable number of rounds.
-Usage
-=====
-Supporting a variable sized salt and variable number of rounds,
-this scheme is used in exactly the same way as :doc:`sha512_crypt <passlib.hash.sha512_crypt>`.
+.. seealso::
+ :ref:`password hash usage <password-hash-examples>` --
+ for examples of how to use this class via the common hash interface.
-Functions
+Interface
=========
.. autoclass:: sha1_crypt()
+.. note::
+
+ This class will use the first available of two possible backends:
+
+ * stdlib :func:`crypt()`, if the host OS supports sha1-crypt (NetBSD).
+ * a pure python implementation of sha1-crypt built into Passlib.
+
+ You can see which backend is in use by calling the :meth:`get_backend()` method.
+
Format
======
An example hash (of ``password``) is ``$sha1$40000$jtNX3nZ2$hBNaIXkt4wBI2o5rsi8KejSjNqIq``.
@@ -62,7 +70,7 @@ in a few ways:
The NetBSD implementation randomly varies the actual number of rounds
when generating a new configuration string, in order to decrease
- predictability. This feature is provided by PassLib to *all* hashes,
+ predictability. This feature is provided by Passlib to *all* hashes,
via the :class:`CryptContext` class, and so it omitted
from this implementation.
@@ -72,14 +80,14 @@ in a few ways:
within the rounds portion of the hash. No existing examples
or test vectors have zero padding, and allowing it would
result in multiple encodings for the same configuration / hash.
- To prevent this situation, PassLib will throw an error if the rounds in a hash
+ To prevent this situation, Passlib will throw an error if the rounds in a hash
have leading zeros.
* Restricted salt string character set:
The underlying algorithm can unambigously handle salt strings
which contain any possible byte value besides ``\x00`` and ``$``.
- However, PassLib strictly limits salts to the
+ However, Passlib strictly limits salts to the
:data:`hash64 <passlib.utils.HASH64_CHARS>` character set,
as nearly all implementations of sha1-crypt generate
and expect salts containing those characters.
@@ -92,10 +100,10 @@ in a few ways:
is implied by nearly all known reference hashes.
In order to provide support for unicode strings,
- PassLib will encode unicode passwords using ``utf-8``
+ Passlib will encode unicode passwords using ``utf-8``
before running them through sha1-crypt. If a different
encoding is desired by an application, the password should be encoded
- before handing it to PassLib.
+ before handing it to Passlib.
.. rubric:: Footnotes
diff --git a/docs/lib/passlib.hash.sha256_crypt.rst b/docs/lib/passlib.hash.sha256_crypt.rst
index 9b7adce..bbe9c4e 100644
--- a/docs/lib/passlib.hash.sha256_crypt.rst
+++ b/docs/lib/passlib.hash.sha256_crypt.rst
@@ -4,29 +4,117 @@
.. currentmodule:: passlib.hash
-Defined by the same specification as :class:`~passlib.hash.sha512_crypt`,
-SHA256-Crypt is identical to SHA512-Crypt in almost every way, including
-design and security issues. It's main advantage over SHA512-Crypt is
-that it may be faster on 32 bit operating systems.
+SHA-256 Crypt and SHA-512 Crypt were developed in 2008 by Ulrich Drepper [#f1]_,
+designed as the successor to :class:`~passlib.hash.md5_crypt`. They include fixes
+and advancements such as variable rounds, and use of NIST-approved cryptographic primitives.
+SHA-512 / SHA-256 Crypt are currently the default password hash for many systems
+(notably Linux), and have no known weaknesses.
+SHA-256 Crypt is one of the three hashes Passlib :ref:`recommends <recommended-hashes>`
+for new applications.
+This class can be used directly as follows::
-.. seealso:: :doc:`SHA512-Crypt <passlib.hash.sha512_crypt>`
+ >>> from passlib.hash import sha256_crypt
-Usage
-=====
-This class can be used in exactly the same manner as :class:`~passlib.hash.sha512_crypt`.
+ >>> # generate new salt, encrypt password
+ >>> hash = sha256_crypt.encrypt("password")
+ >>> hash
+ '$5$rounds=80000$wnsT7Yr92oJoP28r$cKhJImk5mfuSKV9b3mumNzlbstFUplKtQXXMo4G6Ep5'
+
+ >>> # same, but with explict number of rounds
+ >>> sha256_crypt.encrypt("password", rounds=12345)
+ '$5$rounds=12345$q3hvJE5mn5jKRsW.$BbbYTFiaImz9rTy03GGi.Jf9YY5bmxN0LU3p3uI1iUB'
+
+ >>> # verify password
+ >>> sha256_crypt.verify("password", hash)
+ True
+ >>> sha256_crypt.verify("letmein", hash)
+ False
+
+.. seealso::
+
+ * :ref:`password hash usage <password-hash-examples>` -- for more usage examples
+
+ * :doc:`sha512_crypt <passlib.hash.sha512_crypt>` -- the companion 512-bit version of this hash.
Interface
=========
.. autoclass:: sha256_crypt()
+.. note::
+
+ This class will use the first available of two possible backends:
+
+ * stdlib :func:`crypt()`, if the host OS supports SHA256-Crypt (most Linux systems).
+ * a pure python implementation of SHA256-Crypt built into Passlib.
+
+ You can see which backend is in use by calling the :meth:`get_backend()` method.
+
Format & Algorithm
==================
-SHA256-Crypt is defined by the same specification as SHA512-Crypt.
-The format and algorithm are exactly the same, except for
-the following notable differences:
+An example sha256-crypt hash (of the string ``password``) is:
+
+ ``$5$rounds=80000$wnsT7Yr92oJoP28r$cKhJImk5mfuSKV9b3mumNzlbstFUplKtQXXMo4G6Ep5``
+
+An sha256-crypt hash string has the format :samp:`$5$rounds={rounds}${salt}${checksum}`, where:
+
+* ``$5$`` is the prefix used to identify sha256-crypt hashes,
+ following the :ref:`modular-crypt-format`
+
+* :samp:`{rounds}` is the decimal number of rounds to use (80000 in the example).
+
+* :samp:`{salt}` is 0-16 characters drawn from ``[./0-9A-Za-z]``, providing a
+ 96-bit salt (``wnsT7Yr92oJoP28r`` in the example).
+
+* :samp:`{checksum}` is 43 characters drawn from the same set, encoding a 256-bit
+ checksum (``cKhJImk5mfuSKV9b3mumNzlbstFUplKtQXXMo4G6Ep5`` in the example).
+
+There is also an alternate format :samp:`$5${salt}${checksum}`,
+which can be used when the rounds parameter is equal to 5000
+(see the ``implicit_rounds`` parameter above).
+
+The algorithm used by SHA256-Crypt is laid out in detail
+in the specification document linked to below [#f1]_.
+
+Deviations
+==========
+This implementation of sha256-crypt differs from the specification,
+and other implementations, in a few ways:
+
+* Zero-Padded Rounds:
+
+ The specification does not specify how to deal with zero-padding
+ within the rounds portion of the hash. No existing examples
+ or test vectors have zero padding, and allowing it would
+ result in multiple encodings for the same configuration / hash.
+ To prevent this situation, Passlib will throw an error if the rounds
+ parameter in a hash has leading zeros.
+
+* Restricted salt string character set:
+
+ The underlying algorithm can unambigously handle salt strings
+ which contain any possible byte value besides ``\x00`` and ``$``.
+ However, Passlib strictly limits salts to the
+ :data:`hash64 <passlib.utils.HASH64_CHARS>` character set,
+ as nearly all implementations of sha256-crypt generate
+ and expect salts containing those characters,
+ but may have unexpected behaviors for other character values.
+
+* Unicode Policy:
+
+ The underlying algorithm takes in a password specified
+ as a series of non-null bytes, and does not specify what encoding
+ should be used; though a ``us-ascii`` compatible encoding
+ is implied by nearly all implementations of sha256-crypt
+ as well as all known reference hashes.
+
+ In order to provide support for unicode strings,
+ Passlib will encode unicode passwords using ``utf-8``
+ before running them through sha256-crypt. If a different
+ encoding is desired by an application, the password should be encoded
+ before handing it to Passlib.
-* it uses the :ref:`modular crypt prefix <modular-crypt-format>` ``$5$``, whereas SHA-512-Crypt uses ``$6$``.
-* it uses the SHA-256 message digest in place of the SHA-512 message digest.
-* it's output hash is correspondingly smaller in size, encoding a 256 bit checksum instead of 512.
+.. rubric:: Footnotes
-See SHA512-Crypt for more details.
+.. [#f1] Ulrich Drepper's SHA-256/512-Crypt specification, reference
+ implementation, and test vectors -
+ `sha-crypt specification <http://www.akkadia.org/drepper/sha-crypt.html>`_
diff --git a/docs/lib/passlib.hash.sha512_crypt.rst b/docs/lib/passlib.hash.sha512_crypt.rst
index 963c61f..7e52d50 100644
--- a/docs/lib/passlib.hash.sha512_crypt.rst
+++ b/docs/lib/passlib.hash.sha512_crypt.rst
@@ -4,112 +4,43 @@
.. currentmodule:: passlib.hash
-SHA-512 Crypt and SHA-256 Crypt were developed in 2008 by Ulrich Drepper [#f1]_
-as a successor to :class:`~passlib.hash.md5_crypt`. They include fixes
-and advancements such as variable rounds, and use of NIST-approved cryptographic primitives.
-SHA-256 / SHA-512 Crypt are currently the default password hash for many systems
-(notably Linux), and have no known weaknesses.
-SHA-512 Crypt is one of the three hashes Passlib :ref:`recommends <recommended-hashes>`
-for new applications.
+Defined by the same specification as :class:`~passlib.hash.sha256_crypt`,
+SHA512-Crypt is identical to SHA256-Crypt in almost every way, including
+design and security issues. The only difference is the doubled digest size;
+while this provides some increase in security, it's also a bit slower 32 bit operating systems.
-Usage
-=====
-This class can be used directly as follows::
+.. seealso::
- >>> from passlib.hash import sha512_crypt as sc
+ * :ref:`password hash usage <password-hash-examples>` --
+ for examples of how to use this class via the common hash interface.
- >>> #generate new salt, encrypt password
- >>> h = sc.encrypt("password")
- >>> h
- '$6$rounds=40000$xCsOXRqPPk5AGDFu$o5eyqxEoOSq0dLRFbPxEHp5Jc1vFVj47BNT.h9gmjSHXDS15mjIM.GSUaT5r6Z.Xa1Akrv4FAgKJE3EfbkJxs1'
-
- >>> #same, but with explict number of rounds
- >>> sc.encrypt("password", rounds=10000)
- '$6$rounds=10000$QWT8AlDMYRms7vSx$.1267Pg6Opn9CblFndtBJ2Q0AI0fcI2IX93zX3gi1Qse./j.VlKYX59NIUlbs0A66wCbfu/vra9wMv2uwTZAI.'
-
- >>> #check if hash is recognized
- >>> sc.identify(h)
- True
- >>> #check if some other hash is recognized
- >>> sc.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31')
- False
-
- >>> #verify correct password
- >>> sc.verify("password", h)
- True
- >>> sc.verify("secret", h) #verify incorrect password
- False
+ * :doc:`sha256_crypt <passlib.hash.sha256_crypt>` -- the companion 256-bit version
+ of this hash.
Interface
=========
.. autoclass:: sha512_crypt()
-Format & Algorithm
-==================
-An example sha512-crypt hash (of the string ``password``) is:
-
- ``$6$rounds=40000$JvTuqzqw9bQ8iBl6$SxklIkW4gz00LvuOsKRCfNEllLciOqY/FSAwODHon45YTJEozmy.QAWiyVpuiq7XMTUMWbIWWEuQytdHkigcN/``.
-
-An sha512-crypt hash string has the format :samp:`$6$rounds={rounds}${salt}${checksum}`, where:
-
-* ``$6$`` is the prefix used to identify sha512-crypt hashes,
- following the :ref:`modular-crypt-format`
-
-* :samp:`{rounds}` is the decimal number of rounds to use (40000 in the example).
-
-* :samp:`{salt}` is 0-16 characters drawn from ``[./0-9A-Za-z]``, providing a
- 96-bit salt (``JvTuqzqw9bQ8iBl6`` in the example).
-
-* :samp:`{checksum}` is 86 characters drawn from the same set, encoding a 512-bit
- checksum.
+.. note::
- (``SxklIkW4gz00LvuOsKRCfNEllLciOqY/FSAwODHon45YTJEozmy.QAWiyVpuiq7XMTUMWbIWWEuQytdHkigcN/`` in the example).
+ This class will use the first available of two possible backends:
-There is also an alternate format :samp:`$6${salt}${checksum}`,
-which can be used when the rounds parameter is equal to 5000
-(see the ``implicit_rounds`` parameter above).
+ * stdlib :func:`crypt()`, if the host OS supports SHA512-Crypt (most Linux systems).
+ * a pure python implementation of SHA512-Crypt built into passlib.
-The algorithm used by SHA512-Crypt is laid out in detail
-in the specification document linked to below [#f1]_.
+ You can see which backend is in use by calling the :meth:`get_backend()` method.
-Deviations
-==========
-This implementation of sha512-crypt differs from the specification,
-and other implementations, in a few ways:
-
-* Zero-Padded Rounds:
-
- The specification does not specify how to deal with zero-padding
- within the rounds portion of the hash. No existing examples
- or test vectors have zero padding, and allowing it would
- result in multiple encodings for the same configuration / hash.
- To prevent this situation, PassLib will throw an error if the rounds
- parameter in a hash has leading zeros.
-
-* Restricted salt string character set:
-
- The underlying algorithm can unambigously handle salt strings
- which contain any possible byte value besides ``\x00`` and ``$``.
- However, PassLib strictly limits salts to the
- :data:`hash64 <passlib.utils.HASH64_CHARS>` character set,
- as nearly all implementations of sha512-crypt generate
- and expect salts containing those characters,
- but may have unexpected behaviors for other character values.
-
-* Unicode Policy:
-
- The underlying algorithm takes in a password specified
- as a series of non-null bytes, and does not specify what encoding
- should be used; though a ``us-ascii`` compatible encoding
- is implied by nearly all implementations of sha512-crypt
- as well as all known reference hashes.
-
- In order to provide support for unicode strings,
- PassLib will encode unicode passwords using ``utf-8``
- before running them through sha512-crypt. If a different
- encoding is desired by an application, the password should be encoded
- before handing it to PassLib.
-
-.. rubric:: Footnotes
-
-.. [#f1] Ulrich Drepper's SHA-256/512-Crypt specification, reference implementation, and test vectors - `sha-crypt specification <http://www.akkadia.org/drepper/sha-crypt.html>`_
+Format & Algorithm
+==================
+SHA512-Crypt is defined by the same specification as SHA256-Crypt.
+The format and algorithm are exactly the same, except for
+the following notable differences:
+
+* it uses the :ref:`modular crypt prefix <modular-crypt-format>` ``$6$``, whereas SHA256-Crypt uses ``$5$``.
+* it uses the SHA-512 message digest in place of the SHA-256 message digest.
+* it's output hash is correspondingly larger in size,
+ with an 86-character encoded checksum, instead of 43 characters.
+
+See :doc:`sha256_crypt <passlib.hash.sha256_crypt>`
+for the format and algorithm descriptions,
+as well as security notes.
diff --git a/docs/lib/passlib.hash.sun_md5_crypt.rst b/docs/lib/passlib.hash.sun_md5_crypt.rst
index 2a5cf4b..deba896 100644
--- a/docs/lib/passlib.hash.sun_md5_crypt.rst
+++ b/docs/lib/passlib.hash.sun_md5_crypt.rst
@@ -11,17 +11,16 @@ It was introduced in Solaris 9u2. While based on the MD5 message digest, it has
in common with the :class:`~passlib.hash.md5_crypt` algorithm. It supports
32 bit variable rounds and an 8 character salt.
-.. warning::
+.. seealso::
+ :ref:`password hash usage <password-hash-examples>` --
+ for examples of how to use this class via the common hash interface.
+
+.. note::
The original Solaris implementation has some hash encoding quirks
which may not be properly accounted for in Passlib.
- For now, this implementation should not be relied on for anything but novelty purposes.
-
-Usage
-=====
-This class supports both rounds and salts,
-and so can be used in the exact same manner
-as :doc:`SHA-512 Crypt <passlib.hash.sha512_crypt>`.
+ Until more user feedback and sample hashes have been gathered,
+ *caveat emptor*.
Interface
=========
@@ -147,7 +146,7 @@ conform to what users are used to.
Deviations
==========
-PassLib's implementation of Sun-MD5-Crypt deliberately
+Passlib's implementation of Sun-MD5-Crypt deliberately
deviates from the official implementation in the following ways:
* Unicode Policy:
@@ -158,10 +157,10 @@ deviates from the official implementation in the following ways:
is implied by all known reference hashes.
In order to provide support for unicode strings,
- PassLib will encode unicode passwords using ``utf-8``
+ Passlib will encode unicode passwords using ``utf-8``
before running them through sun-md5-crypt. If a different
encoding is desired by an application, the password should be encoded
- before handing it to PassLib.
+ before handing it to Passlib.
* Rounds encoding
diff --git a/docs/lib/passlib.hash.unix_disabled.rst b/docs/lib/passlib.hash.unix_disabled.rst
index bfd725d..8a8fece 100644
--- a/docs/lib/passlib.hash.unix_disabled.rst
+++ b/docs/lib/passlib.hash.unix_disabled.rst
@@ -7,41 +7,41 @@
This class does not provide an encryption scheme,
but instead provides a helper for handling disabled
password fields as found in unix ``/etc/shadow`` files.
-
-Usage
-=====
This class is mainly useful only for plugging into a
:class:`~passlib.context.CryptContext` instance.
It can be used directly as follows::
- >>> from passlib.hash import unix_disabled as ud
+ >>> from passlib.hash import unix_disabled
>>> # 'encrypting' a password always results in "!" or "*"
- >>> ud.encrypt("password")
+ >>> unix_disabled.encrypt("password")
'!'
>>> # verifying will fail for all passwords and hashes
- >>> ud.verify("password", "!")
+ >>> unix_disabled.verify("password", "!")
False
- >>> ud.verify("letmein", "*NOPASSWORD*")
+ >>> unix_disabled.verify("letmein", "*NOPASSWORD*")
False
- >>> # all strings are recognized - if used in conjunction with other hashes,
- >>> # this should be the last one checked.
- >>> ud.identify('!')
+ >>> # this class will positively identify all strings - so if it's used
+ >>> # in conjunction with other hashes, this should be the last one checked.
+ >>> unix_disabled.identify('!')
True
- >>> ud.identify('*')
+ >>> unix_disabled.identify('*')
True
- >>> ud.identify('')
+ >>> unix_disabled.identify('')
True
-
Interface
=========
-.. autoclass:: unix_disabled
+.. autoclass:: unix_disabled()
+
+Deprecated Interface
+====================
+.. autoclass:: unix_fallback()
Deviations
==========
According to the Linux ``shadow`` man page, an empty string is treated
as a wildcard by Linux, allowing all passwords. For security purposes,
-this behavior is NOT supported; empty strings are treated the same as ``!``.
+this behavior is NOT supported; empty strings are treated the same as ``!`` or ``*``.
diff --git a/docs/password_hash_api.rst b/docs/password_hash_api.rst
index c349992..e0ce49b 100644
--- a/docs/password_hash_api.rst
+++ b/docs/password_hash_api.rst
@@ -1,612 +1,675 @@
.. index::
- single: password hash api
+ single: PasswordHash interface
single: custom hash handler; requirements
-.. currentmodule:: passlib.hash
+.. module:: passlib.ifc
+ :synopsis: abstract interfaces used by Passlib
.. _password-hash-api:
-=================
-Password Hash API
-=================
+=============================================
+Password Hash Interface
+=============================================
Overview
========
-All of the hashes supported by PassLib are implemented using classes [#otypes]_
-which support an identical interface; this document describes that
-interface in terms of a non-existent abstract class called :class:`!PasswordHash`.
-All of the supported password hashes [#supported]_ provide the following methods and attributes:
+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:
-:ref:`required-attributes`
+.. class:: PasswordHash()
- These consist of the attributes :attr:`~PasswordHash.name`,
- :attr:`~PasswordHash.setting_kwds`, and :attr:`~PasswordHash.context_kwds`.
- They permit users and applications to detect what features a specific :class:`!PasswordHash`
- allows and/or requires.
+ 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:
-:ref:`application-methods`
+ * :meth:`~PasswordHash.encrypt` - generate new salt, return hash of password.
+ * :meth:`~PasswordHash.verify` - verify password against existing hash.
- This interface consists of the :meth:`~PasswordHash.encrypt`,
- :meth:`~PasswordHash.identify`, and :meth:`~PasswordHash.verify` classmethods.
- These are the methods most applications will need to make use of.
+ While not needed by most applications, the following methods
+ provide an interface that mimics the traditional Unix :func:`crypt`
+ function:
-:ref:`crypt-methods`
+ * :meth:`~PasswordHash.genconfig` - create configuration string from salt & other options.
+ * :meth:`~PasswordHash.genhash` - hash password using existing hash or configuration string.
- This interface consists of the :meth:`~PasswordHash.genconfig`
- and :meth:`~PasswordHash.genhash` classmethods.
- These methods mimic the standard unix crypt interface,
- and are not usually needed by applications.
+ One additional support method is provided:
-:ref:`optional-attributes`
+ * :meth:`~PasswordHash.identify` - check if hash belongs to this algorithm.
- These attributes provide additional information
- about the capabilities and limitations of certain password hash schemes.
+ Each hash algorithm also provides a number of :ref:`informational attributes <informational-attributes>`,
+ allowing programmatic inspection of it's options and parameter limits.
-Usage
-=====
-While most uses of PassLib are done through a :class:`~passlib.context.CryptContext` class,
-the various :class:`!PasswordHash` classes can be used directly to manipulate
-passwords::
+.. _password-hash-examples:
- >>> # for example, the SHA256-Crypt class:
- >>> from passlib.hash import sha256_crypt as sc
+Usage Examples
+==============
+The following code shows how to use the primary
+methods of the :class:`~passlib.utils.handlers.PasswordHash` interface --
+:meth:`~PasswordHash.encrypt` and :meth:`~PasswordHash.verify` --
+using the :class:`~passlib.hash.sha256_crypt` hash as an example::
- >>> # using it to encrypt a password:
- >>> h = sc.encrypt("password")
- >>> h
+ >>> # import the handler class
+ >>> from passlib.hash import sha256_crypt
+
+ >>> # hash a password using the default settings:
+ >>> hash = sha256_crypt.encrypt("password")
+ >>> hash
'$5$rounds=40000$HIo6SCnVL9zqF8TK$y2sUnu13gp4cv0YgLQMW56PfQjWaTyiHjVbXTgleYG9'
- >>> # subsequent calls to sc.encrypt() will generate a new salt:
- >>> sc.encrypt("password")
+ >>> # note that each call to encrypt() generates a new salt,
+ >>> # and thus the contents of the hash will differ, despite using the same password:
+ >>> sha256_crypt.encrypt("password")
'$5$rounds=40000$1JfxoiYM5Pxokyh8$ez8uV8jjXW7SjpaTg2vHJmx3Qn36uyZpjhyC9AfBi7B'
- >>> # the same, but with an explict number of rounds:
- >>> sc.encrypt("password", rounds=10000)
- '$5$rounds=10000$UkvoKJb8BPrLnR.D$OrUnOdr.IJx74hmyyzuRdr5k9lSXdkFxKmr7bLQTty5'
+ >>> # if the hash supports a variable number of iterations (which sha256_crypt does),
+ >>> # you can override the default value via the 'rounds' keyword:
+ >>> sha256_crypt.encrypt("password", rounds=12345)
+ '$5$rounds=12345$UeVpHaN2YFDwBoeJ$NJN8DwVZ4UfQw6.ijJZNWoZtk1Ivi5YfKCDsI2HzSq2'
- >>> #the identify method can be used to determine the format of an unknown hash:
- >>> sc.identify(h)
+ >>> # on the other end of things, the verify() method takes care of
+ >>> # checking if a password matches an existing hash string:
+ >>> sha256_crypt.verify("password", hash)
True
-
- >>> #check if some other hash is recognized (in this case, an MD5-Crypt hash)
- >>> sc.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31')
+ >>> sha256_crypt.verify("letmeinplz", hash)
False
- >>> #the verify method encapsulates all hash comparison logic for a class:
- >>> sc.verify("password", h)
+.. note::
+
+ Whether a hash supports a particular configuration keywoard (such as ``rounds``)
+ can be determined from it's documentation page; but also programmatically from
+ it's :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 sha256_crypt, md5_crypt
+ >>> other_hash = md5_crypt.encrypt("password")
+ >>> sha256_crypt.verify("password", other_hash)
+ Traceback (most recent call last):
+ <traceback omitted>
+ ValueError: not a valid sha256_crypt hash
+
+ >>> # this can be prevented by using the identify method,
+ >>> # determines whether a hash belongs to a given algorithm:
+ >>> hash = sha256_crypt.encrypt("password")
+ >>> sha256_crypt.identify(hash)
True
- >>> sc.verify("wrongpassword", h)
+ >>> sha256_crypt.identify(other_hash)
False
-.. _required-attributes:
+While the initial :meth:`~PasswordHash.encrypt` 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::
-Required Attributes
-=================================
-.. attribute:: PasswordHash.name
+ >>> # for oracle10, encrypt requires a username:
+ >>> from passlib.hash import oracle10
+ >>> hash = oracle10.encrypt("secret", user="admin")
+ 'B858CE295C95193F'
- A unique name used to identify
- the particular scheme this class implements.
+ >>> # 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
- These names should consist only of lowercase a-z, the digits 0-9, and underscores.
+ >>> # 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
- .. note::
+ >>> # forgetting to include the username when it's required will cause a TypeError:
+ >>> hash = oracle10.encrypt("password")
+ Traceback (most recent call last):
+ <traceback omitted>
+ TypeError: user must be unicode or bytes, not None
- All handlers built into passlib are implemented as classes
- located under :samp:`passlib.hash.{name}`, where :samp:`{name}`
- is both the class name, and the value of the ``name`` attribute.
- This is not a requirement, and may not be true for
- externally-defined handlers.
+.. note::
-.. attribute:: PasswordHash.setting_kwds
+ Whether a hash requires external parameters (such as ``user``)
+ can be determined from it's documentation page; but also programmatically from
+ it's :attr:`~PasswordHash.context_kwds` attribute.
- If the scheme supports per-hash configuration
- (such as salts, variable rounds, etc), this attribute
- should contain a tuple of keywords corresponding
- to each of those configuration options.
- This should list all the main configuration keywords accepted
- by :meth:`~PasswordHash.genconfig` and :meth:`~PasswordHash.encrypt`.
- If no configuration options are supported, this attribute should be an empty tuple.
+.. _primary-methods:
- While each class may support a variety of options, each with their own meaning
- and semantics, the following keywords should have the same behavior
- across all schemes which use them:
+Primary Methods
+===============
+Most applications will only need to use two methods:
+:meth:`~PasswordHash.encrypt` 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,
+and hash comparison.
- ``salt``
- If present, this means the algorithm contains some number of bits of salt
- which should vary with every new hash created.
+.. classmethod:: PasswordHash.encrypt(secret, \*\*kwds)
- Additionally, this means
- :meth:`~PasswordHash.genconfig` and :meth:`~PasswordHash.encrypt`
- should both accept an optional ``salt`` keyword allowing the user
- to specify a bare salt string. Note that this feature is rarely
- needed, and the constraints on the size & content of this string
- will vary for each algorithm.
+ Encrypt password, returning resulting hash string.
- ``salt_size``
- Most algorithms which support ``salt`` will auto-generate a salt string
- if none is provided. If this keyword is also present, it means it
- can be used to select the size of the auto-generated salt.
- If omitted, most algorithms will fall back to a default salt size.
+ :type secret: unicode or bytes
+ :arg secret: string containing the password to encode.
- ``rounds``
- If present, this means the algorithm allows for a variable number of rounds
- to be used, allowing the processor time required to be increased.
+ :param \*\*kwds:
- Providing this as a keyword should allow the application to
- override the class' default number of rounds. While this
- must be a non-negative integer for all implementations,
- additional constraints may be present for each algorith
- (such as the cost varying on a linear or logarithmic scale).
+ 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`.
+ Examples of common keywords include ``salt`` and ``rounds``.
- ``ident``
- If present, the class supports multiple formats for encoding
- the same hash. The class's documentation will generally list
- the allowed values, allowing alternate output formats to be selected.
+ :returns:
+ resulting hash, using an algorithm-specific format.
- ``relaxed``
- If supported, ``relaxed=True`` will cause the handler to
- be more forgiving about invalid input. Instead of immediately throwing
- a :exc:`ValueError`, it will first attempt to correct the input,
- and issue a :exc:`~passlib.exc.PasslibHashWarning` if successful.
- This includes actions like clamping out-of-range rounds values,
- and truncating salts that are too long.
+ this will use the native :class:`!str` type
+ (unicode under Python 3, ``ascii``-encoded bytes under Python 2).
-.. attribute:: PasswordHash.context_kwds
+ :raises ValueError:
- This attribute should contain a tuple of keywords
- which should be passed into :func:`encrypt`, :func:`verify`,
- and :func:`genhash` in order to encrypt a password.
+ * If a keyword's value is invalid (e.g. if a ``salt`` string
+ is too small, or a ``rounds`` value is out of range).
- Some algorithms require external contextual information
- in order to generate a checksum for a password.
- An example of this is :doc:`Postgres' MD5 algorithm <lib/passlib.hash.postgres_md5>`,
- which requires the username be provided when generating a hash
- (see that class for an example of how this works in pratice).
+ * If the *secret* contains characters forbidden by the handler
+ (e.g. :class:`!des_crypt` forbids NULL characters).
- Since most password hashes require no external information,
- this tuple will usually be empty, and references
- to context keywords can be ignored for all but a few classes.
+ :raises TypeError:
- While each class may support a variety of options, each with their own meaning
- and semantics, the following keywords should have the same behavior
- across all schemes which use them:
+ * if :samp:`{secret}` is not unicode or bytes.
+ * if a keyword argument had an incorrect type.
+ * if a required keyword was not provided.
- ``user``
+ .. versionchanged:: 1.6
+ Hashes now raise :exc:`TypeError` if a required keyword is missing,
+ rather than :exc:`ValueError` like in previous releases; in order
+ to conform with normal Python behavior.
- If present, the class requires a username be specified whenever
- performing a hash calculation (eg: postgres_md5 and oracle10).
+ .. versionchanged:: 1.6
+ Passlib is now much stricter about input validation: for example,
+ out-of-range ``rounds`` values now cause an error instead of being
+ clipped (though applications may set ``relaxed=True`` to restore the old behavior).
-.. _application-methods:
+.. classmethod:: PasswordHash.verify(secret, hash, \*\*context_kwds)
-Application Methods
-===================
-The :meth:`~PasswordHash.encrypt`, :meth:`~PasswordHash.identify`, and :meth:`~PasswordHash.verify` methods are designed
-to provide an easy interface for applications. They allow encrypt new passwords
-without having to deal with details such as salt generation, verifying
-passwords without having to deal with hash comparison rules, and determining
-which scheme a hash belongs to when multiple schemes are in use.
+ Verify a secret using an existing hash.
-.. classmethod:: PasswordHash.encrypt(secret, \*\*settings_and_context_kwds)
+ This checks if a secret matches against the one stored
+ inside the specified hash.
- encrypt secret, returning resulting hash string.
+ :type secret: unicode or bytes
+ :param secret:
+ A string containing the password to check.
- :arg secret:
- A string containing the secret to encode.
+ :type secret: unicode or bytes
+ :param hash:
+ A string containing the hash to check against.
- Unicode behavior is specified on a per-hash basis,
- but the common case is to encode into utf-8
- before processing.
+ Hashes may be specified as :class:`!unicode` or
+ ``ascii``-encoded :class:`!bytes`.
- :param \*\*settings_and_context_kwds:
- All other keywords are algorithm-specified,
- and should be listed in :attr:`~PasswordHash.setting_kwds`
- and :attr:`~PasswordHash.context_kwds`.
+ :param \*\*kwds:
+ Very few hashes will have additional keywords.
+
+ 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.encrypt` call when the hash was generated,
+ or the password will not verify.
- Common settings keywords include ``salt`` and ``rounds``.
+ 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`.
+ Examples of common keywords include ``user``.
+
+ :returns:
+ ``True`` if the secret matches, otherwise ``False``.
+
+ :raises TypeError:
+ * if either *secret* or *hash* is not a unicode or bytes instance.
+ * if the hash requires additional keywords which are not provided,
+ or have the wrong type.
:raises ValueError:
+ * if *hash* does not match this algorithm's format.
+ * if the secret contains forbidden characters (see
+ :meth:`~PasswordHash.encrypt`).
+ * 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).
- * If a keyword's value is invalid (e.g. if a ``salt`` string
- is too small, or a ``rounds`` value is out of range).
+ .. versionchanged:: 1.6
+ This function now raises :exc:`ValueError` if a ``None`` or config string is provided
+ instead of a proper hash; previous releases were inconsistent
+ in their handling of these cases.
- * If the secret contains characters forbidden by the handler
- (e.g. :class:`!des_crypt` forbids NULL characters). This should not
- happen often, since most modern algorithms have no limitations on
- the character values they accept.
+.. _hash-unicode-behavior:
- :raises TypeError:
+.. note::
- * if :samp:`{secret}` is not a unicode or bytes instance.
+ Regarding unicode passwords & non-ASCII characters:
- * if a required option (such as a context keyword) was not set.
+ 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:
- :returns:
- Hash string, using an algorithm-specific format.
+ * 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.
- .. versionchanged:: 1.6
+ * For historical reasons, :class:`~passlib.hash.lmhash` uses ``cp437``
+ as it's default encoding. It will handle :class:`!unicode` correctly,
+ but non-``ascii`` passwords provided as :class:`!bytes` must be encoded
+ using ``"cp437"``, or the correct encoding must be specified via :class:`!lmhash`'s
+ ``encoding`` keyword.
- Previous versions of Passlib would raise :exc:`ValueError` if a
- required keyword was missing; this has been changed to :exc:`TypeError`
- in order to conform with normal Python behavior.
+.. _crypt-methods:
- Previous versions of Passlib would silently correct invalid settings
- where possible (e.g. silently clamping out-of-range ``rounds``); as
- of Passlib 1.6 the policy is to raise an explicit error.
+Crypt Methods
+=============
+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
+using the provided configuration string.
-.. classmethod:: PasswordHash.identify(hash)
+.. seealso::
- Quickly identify if a hash string belongs to this algorithm.
+ Most applications will find :meth:`~PasswordHash.encrypt` much more useful,
+ as it combines the functionality of these two methods into one.
+
+.. classmethod:: PasswordHash.genconfig(\*\*setting_kwds)
+
+ Returns a configuration string encoding settings for hash generation.
- :arg hash: the candidate hash string to check
+ This function takes in all the same :attr:`~PasswordHash.setting_kwds`
+ as :meth:`~PasswordHash.encrypt`, fills in suitable defaults,
+ and encodes the settings into a single "configuration" string,
+ suitable passing to :meth:`~PasswordHash.genhash`.
- :raises TypeError: if :samp:`{hash}` is not a unicode or bytes instance.
+ :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`
+ Examples of common keywords include ``salt`` and ``rounds``.
:returns:
- ``True`` if the input appears to be a hash or configuration string
- which belongs to this algorithm, otherwise ``False``.
+ A configuration string (as :class:`!str`), or ``None`` if the scheme
+ does not support a separate configuration.
+
+ :raises ValueError, TypeError:
+ This function raises exceptions for the same
+ reasons as :meth:`~PasswordHash.encrypt`.
.. note::
- The goal of this method is positively identify the correct
- handler for a given hash, and do it as efficiently as possible.
- In order to accomplish this, many implementations perform only minimal
- validation of the candidate hashes. Thus, they may return ``True``
- for hashes which are identifiable, but malformed enough that
- a :exc:`ValueError` is raised when the string is passed to
- :func:`~PasswordHash.verify` or :func:`~PasswordHash.genhash`.
- Because of this, applications should rely on this method only for identification,
- not confirmation that a hash is correctly formed.
+ This configuration string is typically the same as the full hash string,
+ except that it lacks the final portion containing the digested password.
+ This is sometimes referred to as a "salt" string, though it typically
+ contains much more than just the salt parameter.
-.. classmethod:: PasswordHash.verify(secret, hash, \*\*context_kwds)
+.. classmethod:: PasswordHash.genhash(secret, config, \*\*context_kwds)
- verify a secret against an existing hash.
+ Encrypt secret using specified configuration string.
- This checks if a secret matches against the one stored
- inside the specified hash.
+ This takes in a password and a configuration string,
+ and returns a hash for that password.
- :param secret:
- A string containing the secret to check.
- :param hash:
- A string containing the hash to check against.
+ :type secret: unicode or bytes
+ :arg secret:
+ string containing the password to be encrypted.
- :param \*\*context_kwds:
- Any additional keywords will be passed to the encrypt
- method. These should be limited to those listed
- in :attr:`~PasswordHash.context_kwds`.
+ :type config: unicode or bytes or ``None``
+ :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`.
- :raises TypeError:
+ ``None`` is accepted *only* for the hashes which lack a configuration
+ string (for which :meth:`~PasswordHash.genconfig` always returns ``None``).
- if either *secret* or *hash* is not a unicode or bytes instance.
+ :param \*\*kwds:
+ Very few hashes will have additional keywords.
- :raises ValueError:
- * the hash does not match this algorithm's hash format.
- * if the secret contains forbidden characters (see
- :meth:`~PasswordHash.encrypt`).
- * if a configuration string from :meth:`~PasswordHash.genconfig`
- is passed in as the value for *hash*.
+ 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.encrypt` 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`.
+ Examples of common keywords include ``user``.
:returns:
- ``True`` if the secret matches, otherwise ``False``.
+ Encoded hash matching specified secret, config, and kwds.
+ This will always be a native :class:`!str` instance.
-.. _crypt-methods:
+ :raises ValueError, TypeError:
+ This function raises exceptions for the same
+ reasons as :meth:`~PasswordHash.encrypt`.
-Crypt Methods
-=============
-While the application methods are generally the most useful when integrating
-password support into an application, those methods are for the most part
-built on top of the crypt interface, which is somewhat simpler
-for *implementing* new password schemes. It also happens to match
-more closely with the crypt api of most Unix systems,
-and consists of two functions: :meth:`~PasswordHash.genconfig`
-and :meth:`~PasswordHash.genhash`.
+ .. warning::
-.. classmethod:: PasswordHash.genconfig(\*\*settings_kwds)
+ Traditionally, password verification using the "crypt" interface
+ was done by testing if ``hash == genhash(password, hash)``.
+ This test is only reliable for a handful of algorithms,
+ as various hash representation issues may cause false results.
+ Applications are strongly urged to use :meth:`~PasswordHash.verify` instead.
- returns configuration string encoding settings for hash generation
+.. _support-methods:
- Many hashes have configuration options, and support a format
- which encodes them into a single configuration string.
- (This configuration string is usually an abbreviated version of their
- encoded hash format, sans the actual checksum, and is commonly
- referred to as a ``salt string``, though it may contain much more
- than just a salt).
+Support Methods
+===============
+There is currently one additional support method, :meth:`~PasswordHash.identify`:
- This function takes in configuration options specific to the handler,
- validates the inputs, fills in defaults where appropriate, and returns
- a configuration string. For algorithms which do not have any configuration
- options, this function should always return ``None``.
+.. classmethod:: PasswordHash.identify(hash)
- :param \*\*settings_kwds:
+ Quickly identify if a hash string belongs to this algorithm.
- While each algorithm may have it's own specific configuration options
- (detailed in it's documentation), a list of common options can be
- found in in :attr:`~PasswordHash.setting_kwds`.
+ :type hash: unicode or bytes
+ :arg hash:
+ the candidate hash string to check
- commonly supported keywords include ``salt`` and ``rounds``.
+ :returns:
+ * ``True`` if the input is a configuration string or hash string
+ identifiable as belonging to this scheme (even if it's malformed).
+ * ``False`` if the input does *not* belong to this scheme.
+ * Hashes which lack a reliable method of identification may incorrectly
+ identify each-other's hashes (e.g. both :class:`~passlib.hash.lmhash`
+ and :class:`~passlib.hash.nthash` hash consist 32 hexidecimal characters).
:raises TypeError:
- if any required configuration options are omitted
- (most options do not need to be specified; e.g. an appropriate
- value for ``salt`` will be autogenerated for each call).
+ if :samp:`{hash}` is not a unicode or bytes instance.
- :raises ValueError:
- if any configuration options are invalid (and cannot
- be corrected, if in relaxed parsing mode).
+ .. seealso::
- :returns:
- the configuration string, or ``None`` if the algorithm does not support
- any configuration options.
+ If you are considering using this method to select from multiple
+ algorithms in order to verify a password, you may be better served
+ by the :doc:`CryptContext </lib/passlib.context>` class.
-.. classmethod:: PasswordHash.genhash(secret, config, \*\*context_kwds)
+..
+ the undocumented and experimental support methods currently include
+ parsehash() and bitsize()
- encrypt secret to hash
+.. _informational-attributes:
- takes in a password, optional configuration string,
- and any required contextual information the algorithm needs,
- and returns the encoded hash strings.
+Informational Attributes
+========================
- :arg secret: string containing the password to be encrypted
- :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`.
+.. _general-attributes:
- :param \*\*context_kwds:
- All other keywords must be external contextual information
- required by the algorithm to create the hash. If any,
- these kwds must be specified in :attr:`~PasswordHash.context_kwds`.
+General Information
+-------------------
+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
+the hashes in passlib:
- :raises TypeError:
- * if either *secret* or *config* is not a unicode or bytes instance.
- * if required contextual keywords are not provided
+.. attribute:: PasswordHash.name
- :raises ValueError:
- * if the configuration string is not in a recognized format.
- * if the secret contains a forbidden character (rare, but some algorithms have limitations, eg: forbidding null characters)
- * if the contextual information is invalid
+ Name uniquely identifying this hash.
- :returns:
- encoded hash matching specified secret, config, and context.
+ For the hashes built into Passlib, this will always match
+ the location where it was imported from — :samp:`passlib.hash.{name}` —
+ though externally defined hashes may not adhere to this.
-.. _optional-attributes:
+ This should always be a :class:`!str` consisting of lowercase ``a-z``,
+ the digits ``0-9``, and the underscore character ``_``.
-Optional Attributes
-=================================
-Many of the handlers expose the following informational
-attributes (though their presence is not uniform or required
-as of this version of Passlib).
+.. attribute:: PasswordHash.setting_kwds
-.. todo::
+ Tuple listing the keywords supported by :meth:`~PasswordHash.encrypt`
+ and :meth:`~PasswordHash.genconfig` that control hash generation, and which will
+ be encoded into the resulting hash.
- Consider making these attributes required for all hashes
- which support the appropriate keyword in :attr:`~PasswordHash.setting_kwds`.
+ This list commonly includes keywords for controlling salt generation,
+ adjusting time-cost parameters, etc. Most of these settings are optional,
+ and suitable defaults will be chosen if they are omitted (e.g. salts
+ will be autogenerated).
-.. _optional-rounds-attributes:
+ While the documentation for each hash should have a complete list of
+ the specific settings the hash uses, the following keywords should have
+ roughly the same behavior for all the hashes that support them:
-Rounds Information
-------------------
-For schemes which support a variable number of rounds (ie, ``'rounds' in PasswordHash.setting_kwds``),
-the following attributes are usually exposed.
-(Applications can test for this suites' presence by using :func:`~passlib.utils.has_rounds_info`)
+ ``salt``
+ Specifies a fixed salt string to use, rather than randomly
+ generating one.
-.. attribute:: PasswordHash.max_rounds
+ This option is supported by most of the hashes in Passlib,
+ though typically it isn't used, as random generation of a salt
+ is usually the desired behavior.
- The maximum number of rounds the scheme allows.
- Specifying values above this will generally result
- in a warning, and :attr:`~!PasswordHash.max_rounds` will be used instead.
- Must be a positive integer.
+ Hashes typically require this to be a :class:`!unicode` or
+ :class:`!bytes` instance, with additional constraints
+ appropriate to the algorithm.
-.. attribute:: PasswordHash.min_rounds
+ ``salt_size``
- The minimum number of rounds the scheme allows.
- Specifying values below this will generally result
- in a warning, and :attr:`~!PasswordHash.min_rounds` will be used instead.
- Must be within ``range(0, max_rounds+1)``.
+ Most algorithms which support the ``salt`` setting will
+ autogenerate a salt when none is provided. Many of those
+ will also offer this option, which allows the caller to specify
+ the size of salt which should be generated. If omitted,
+ the hash's default salt size will be used.
-.. attribute:: PasswordHash.default_rounds
+ ``rounds``
+ If present, this means the hash can vary the number
+ of internal rounds used in some part of it's algorithm,
+ allowing the calculation to take a variable amount of processor
+ time, for increased security.
- The default number of rounds that will be used if not
- explicitly set when calling :meth:`~PasswordHash.encrypt` or :meth:`~PasswordHash.genconfig`.
- Must be within ``range(min_rounds, max_rounds+1)``.
+ While this is almost always a non-negative integer,
+ additional constraints may be present for each algorithm
+ (such as the cost varying on a linear or logarithmic scale).
-.. attribute:: PasswordHash.rounds_cost
+ This value is typically omitted, in which case a default
+ value will be used. The defaults for all the hashes in Passlib
+ are periodically retuned to strike a balance between
+ security and responsiveness.
- Specifies how the rounds value affects the amount of time taken.
- Currently used values are:
+ ``ident``
+ If present, the class supports multiple formats for encoding
+ the same hash. The class's documentation will generally list
+ the allowed values, allowing alternate output formats to be selected.
- ``linear``
- time taken scales linearly with rounds value (eg: :class:`~passlib.hash.sha512_crypt`)
+ Note that these values will typically correspond to different
+ revision of the hash algorithm itself, and they may not all
+ offer the same level of security.
- ``log2``
- time taken scales exponentially with rounds value (eg: :class:`~passlib.hash.bcrypt`)
+ ``relaxed``
+ If supported, ``relaxed=True`` will cause the handler to
+ be more forgiving about invalid input. Instead of immediately throwing
+ a :exc:`ValueError`, it will first attempt to correct the input,
+ and issue a :exc:`~passlib.exc.PasslibHashWarning` if successful.
+ This includes actions like clamping out-of-range rounds values,
+ and truncating salts that are too long.
+
+ Many of the hashes in Passlib support this option, even if it's not listed.
+
+.. attribute:: PasswordHash.context_kwds
+
+ Tuple listing the keywords supported by :meth:`~PasswordHash.encrypt`,
+ :meth:`~PasswordHash.verify`, and :meth:`~PasswordHash.genhash` affect the hash, but are
+ not encoded within it, and thus must be provided each time
+ the hash is calculated.
-.. _optional-salt-attributes:
+ This list commonly includes a user account, http realm identifier,
+ etc. Most of these keywords are required by the hashes which support them,
+ as they are frequently used in place of an embedded salt parameter.
+ This is typically an empty tuple for most of the hashes in passlib.
+
+ While the documentation for each hash should have a complete list of
+ the specific context keywords the hash uses,
+ the following keywords should have roughly the same behavior
+ for all the hashes that support them:
+
+ ``user``
+
+ If present, the class requires a username be specified whenever
+ performing a hash calculation (e.g.
+ :class:`~passlib.hash.postgres_md5` and
+ :class:`~passlib.hash.oracle10`).
+
+ ``encoding``
+
+ Some hashes have poorly-defined or host-dependant unicode behavior,
+ and properly hashing a unique password requires providing
+ the correct encoding (e.g. :class:`~passlib.hash.lmhash`).
+ Hashes which provide this keyword will always expose
+ their default encoding programmatically via the
+ :attr:`~PasswordHash.default_encoding` attribute.
+
+.. _salt-attributes:
Salt Information
----------------
-For schemes which support a salt (ie, ``'salt' in PasswordHash.setting_kwds``),
-the following attributes are usually exposed.
-(Applications can test for this suites' presence by using :func:`~passlib.utils.has_salt_info`)
+For schemes which support a salt string,
+``"salt"`` should be listed in their :attr:`~PasswordHash.setting_kwds`,
+and the following attributes should be defined:
.. attribute:: PasswordHash.max_salt_size
- maximum number of characters which will be used
- if a salt string is provided to :meth:`~PasswordHash.genconfig` or :meth:`~PasswordHash.encrypt`.
- must be one of:
-
- * A positive integer - it should accept and silently truncate
- any salt strings longer than this size.
-
- * ``None`` - the scheme should use all characters of a provided salt,
- no matter how large.
+ The maximum number of bytes/characters allowed in the salt.
+ Should either be a positive integer, or ``None`` (indicating
+ the algorithm has no effective upper limit).
.. attribute:: PasswordHash.min_salt_size
- minimum number of characters required for any salt string
- provided to :meth:`~PasswordHash.genconfig` or :meth:`~PasswordHash.encrypt`.
- must be an integer within ``range(0,max_salt_size+1)``.
+ The minimum number of bytes/characters required for the salt.
+ Must be an integer between 0 or :attr:`~PasswordHash.max_salt_size`.
.. attribute:: PasswordHash.default_salt_size
- size of salts generated by genconfig
- when no salt is provided by caller.
- for most hashes, this defaults to :attr:`~PasswordHash.max_salt_size`.
- this value must be within ``range(min_salt_size, max_salt_size+1)``.
+ The default salt size that will be used when generating a salt,
+ assuming ``salt_size`` is not set explicitly. This is typically
+ the same as :attr:`max_salt_size`,
+ or a sane default if ``max_salt_size=None``.
.. attribute:: PasswordHash.salt_chars
- string containing list of all characters which are allowed
- to be specified in salt parameter.
- for most :ref:`MCF <modular-crypt-format>` hashes,
+ A unicode string containing all the characters permitted
+ in a salt string. For most :ref:`MCF <modular-crypt-format>` hashes,
this is equal to :data:`passlib.utils.HASH64_CHARS`.
- this must be a :class:`!unicode` string if the salt is encoded,
- or (rarely) :class:`!bytes` if the salt is manipulating as unencoded raw bytes.
+ For the rare hashes where the ``salt`` parameter must be specified
+ in bytes, this will be a placeholder :class:`!bytes` object containing
+ all 256 possible byte values.
+
+..
+ not yet documentated, want to make sure this is how we want to do things:
+
+ .. 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
+ hashes accept a larger-than-useful range, and this will
+ contain only the "common" values used for generation.
+
+.. _rounds-attributes:
+
+Rounds Information
+------------------
+For schemes which support a variable number of iterations to adjust their time-cost,
+``"rounds"`` should be listed in :attr:`~PasswordHash.setting_kwds`,
+and the following attributes should be defined:
+
+.. attribute:: PasswordHash.max_rounds
+
+ The maximum number of rounds the scheme allows.
+ Specifying a value beyond this will result in a :exc:`ValueError`.
+ Will be a positive integer, or ``None`` (indicating
+ the algorithm has no effective upper limit).
+
+.. attribute:: PasswordHash.min_rounds
+
+ 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`.
+
+.. attribute:: PasswordHash.default_rounds
+
+ The default number of rounds that will be used if none is explicitly
+ provided to :meth:`~PasswordHash.encrypt`.
+ This will always be an integer between :attr:`~PasswordHash.min_rounds`
+ and :attr:`~PasswordHash.max_rounds`.
+
+.. attribute:: PasswordHash.rounds_cost
+
+ While the cost parameter ``rounds`` is an integer, how it corresponds
+ to the amount of time taken can vary between hashes. This attribute
+ indicates the scale used by the hash:
+
+ * ``"linear"`` - time taken scales linearly with rounds value
+ (e.g. :class:`~passlib.hash.sha512_crypt`)
+ * ``"log2"`` - time taken scales exponentially with rounds value
+ (e.g. :class:`~passlib.hash.bcrypt`)
.. todo::
- This section lists the behavior for handlers which accept
- salt strings containing encoded characters.
- Some handlers may instead expect raw bytes for their salt keyword,
- and handle encoding / decoding them internally.
- It should be documented how these attributes
- behave in that situation.
+ Add notes about when/how the default rounds are retuned.
+ For the 1.6 release, all hashes were retuned to take ~250ms
+ on a single 3 ghz cpu core, or more rounds if that was felt
+ to not provide a minimum level of security. Also, there are
+ so many variables affecting relative system performance,
+ that this policy is more of an informed heuristic than a
+ rigid algorithm.
..
- not yet documentated, want to make sure this is how we want to do things:
+ todo: haven't decided if this is how I want the api look before
+ formally publishing it in the documentation:
- .. attribute:: PasswordHash.default_salt_chars
+ .. _password-hash-backends:
- sequence of characters used to generated new salts
- when no salt is provided by caller.
- for most hashes, this is the same as :attr:`!PasswordHash.salt_chars`;
- but some hashes accept a much larger range of values
- than are typically used. This field allows
- the full range to be accepted, while only
- a select subset to be used for generation.
+ Multiple Backends
+ =================
+ .. note::
- xxx: what about a bits_per_salt_char or some such, so effective salt strength
- can be compared?
+ For the most part, applications will not need this interface,
+ outside of perhaps calling the :meth:`~PasswordHash.get_backend`
+ to determine which the active backend.
-.. _hash-unicode-behavior:
+ Some hashes provided by Passlib have multiple backends which they
+ select from at runtime, to provide the fastest implementation available.
+ Algorithms which offer multiple backends will expose the following
+ methods and attributes:
+
+ .. attribute:: PasswordHash.backends
+
+ Tuple listing names of potential backends (which may or may not be available).
+ If this attribute is not present, the hash does not support
+ multiple backends.
+
+ While the names of the backends are specific to the hash algorithm,
+ the following standard names may be present:
+
+ * ``"os_crypt"`` - backend which uses stdlib's :mod:`!crypt` module.
+ this backend will not be available if the underlying host OS
+ does not support the particular hash algorithm.
+
+ * ``"builtin"`` - backend using pure-python implementation built into
+ Passlib. All hashes will have this as their last backend, as a fallback.
+
+ .. method:: PasswordHash.get_backend()
+
+ This method should return the name of the currently active backend
+ that will be used by :meth:`!encrypt` and :meth:`!verify`.
+
+ :raises passlib.exc.MissingBackendError:
+ in the rare case that *no* backends can be loaded.
+
+ .. method:: PasswordHash.has_backend(backend)
+
+ This method can be used to test if a specific backend is available.
+ Returns ``True`` or ``False``.
+
+ .. method:: PasswordHash.set_backend(backend)
+
+ 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"``.
-Unicode Behavior
-================
-
-.. versionadded:: 1.5
-
-Quick summary
--------------
-For the application developer in a hurry:
-
-* Passwords should be provided as :class:`unicode` if possible.
- While they may be provided as :class:`bytes`,
- in that case it is strongly suggested
- they be encoded using ``utf-8`` or ``ascii``.
-
-* Passlib will always return hashes as native python strings.
- This means :class:`unicode` under Python 3,
- and ``ascii``-encoded :class:`bytes` under Python 2.
-
-* Applications should provide hashes as :class:`unicode` if possible.
- However, ``ascii``-encoded :class:`bytes` are also accepted
- under Python 2.
-
-The following sections detail the issues surrounding
-encoding password hashes, and the behavior required
-by handlers implementing this API.
-It can be skipped by the uninterested.
-
-Passwords
----------
-Applications are strongly encouraged to provide passwords
-as :class:`unicode`. Two situations where an application
-might need to provide a password as :class:`bytes`:
-the application isn't unicode aware (lots of python 2 apps),
-or it needs to verify a password hash that used a specific encoding (eg ``latin-1``).
-For either of these cases, application developers should consider
-the following issues:
-
-* Most hashes in Passlib operate on a string of bytes.
- For handlers implementing such hashes,
- passwords provided as :class:`unicode` should be encoded to ``utf-8``,
- and passwords provided as :class:`bytes` should be treated as opaque.
-
- A few of these hashes officially specify this behavior;
- the rest have no preferred encoding at all,
- so this was chosen as a sensible standard behavior.
- Unless the underlying algorithm specifies an alternate policy,
- handlers should always encode unicode to ``utf-8``.
-
-* Because of the above behavior for :class:`unicode` inputs,
- applications which encode their passwords are urged
- to use ``utf-8`` or ``ascii``,
- so that hashes they generate with encoded bytes
- will verify correctly if/when they start using unicode.
-
- Applications which need to verify existing hashes
- using an alternate encoding such as ``latin-1``
- should be wary of this future "gotcha".
-
-* A few hashes operate on :class:`unicode` strings instead.
- For handlers implementing such hashes:
- passwords provided as :class:`unicode` should be handled as appropriate,
- and passwords provided as :class:`bytes` should be treated as ``utf-8``,
- and decoded.
-
- This behavior was chosen in order to be compatible with
- the common case (above), combined with the fact
- that applications should never need to use a specific
- encoding with these hashes, as they are natively unicode.
-
- (Hashes like this include :class:`~passlib.hash.oracle10` and
- :class:`~passlib.hash.nthash`)
-
-Hashes
-------
-With the exception of plaintext passwords,
-literally *all* of the hash formats surveyed by the Passlib authors
-use only the characters found in 7-bit ``ascii``.
-This has caused most password hashing code (in python and elsewhere)
-to draw a very blurry line between :class:`unicode` and :class:`bytes`.
-Because of that, the following behavior was dictated less
-by design requirements, and more by compatibility
-and ease of implementation issues:
-
-* Handlers should accept hashes as either :class:`unicode` or
- as ``ascii``-encoded :class:`bytes`.
-
- This behavior allows applications to provide hashes
- as unicode or as bytes, as they please; making
- (among other things) migration to Python 3 easier.
-
- The primary exception to this is handlers implementing
- plaintext passwords. The implementations in passlib generally
- use ``utf-8`` to encode unicode passwords,
- and reproduce existing passwords as opaque bytes.
-
-* Internally, it is recommended that handlers use
- :class:`unicode` for parsing / formatting
- purposes, and only use :class:`bytes` for decoded
- binary data ready to be passed into their digest routines.
-
-* Handlers should return hashes as native python strings.
- This means :class:`unicode` under Python 3,
- and ``ascii``-encoded :class:`bytes` under Python 2.
-
- This behavior was chosen to fit with Python 3's
- unicode-oriented philosophy, while retaining
- backwards compatibility with Passlib 1.4 and earlier
- under Python 2.
-
-.. rubric:: Footnotes
-
-.. [#otypes] While this specification is written referring to classes and classmethods,
- password hash handlers can be any type of object (instance, module, etc),
- so long as they offer attributes and functions with the required
- signatures. For example, some of the handlers in Passlib are
- instances of the :class:`~passlib.utils.handlers.PrefixWrapper` class.
-
-.. [#supported] all supported password hashes, whether builtin or registered
- from an external source can be found in the :mod:`passlib.hash` module.
+ :raises passlib.exc.MissingBackendError:
+ if the specified backend is not available.
diff --git a/passlib/handlers/bcrypt.py b/passlib/handlers/bcrypt.py
index 5df66e3..19f6952 100644
--- a/passlib/handlers/bcrypt.py
+++ b/passlib/handlers/bcrypt.py
@@ -61,34 +61,32 @@ class bcrypt(uh.HasManyIdents, uh.HasRounds, uh.HasSalt, uh.HasManyBackends, uh.
It supports a fixed-length salt, and a variable number of rounds.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: str
:param salt:
Optional salt string.
If not specified, one will be autogenerated (this is recommended).
If specified, it must be 22 characters, drawn from the regexp range ``[./0-9A-Za-z]``.
+ :type rounds: int
:param rounds:
Optional number of rounds to use.
Defaults to 12, must be between 4 and 31, inclusive.
This value is logarithmic, the actual number of iterations used will be :samp:`2**{rounds}`.
+ :type ident: str
:param ident:
selects specific version of BCrypt hash that will be used.
Typically you want to leave this alone, and let it default to ``2a``,
- but it can be set to ``2`` to use the older version of BCrypt.
-
- It will use the first available of three possible backends:
-
- 1. `py-bcrypt <http://www.mindrot.org/projects/py-bcrypt/>`_, if installed.
- 2. `bcryptor <https://bitbucket.org/ares/bcryptor/overview>`_, if installed.
- 3. stdlib's :func:`crypt.crypt()`, if the host OS supports BCrypt (eg: BSD).
-
- If no backends are available at runtime,
- :exc:`~passlib.exc.MissingBackendError` will be raised
- whenever :meth:`encrypt` or :meth:`verify` are called.
- You can see which backend is in use by calling the
- :meth:`~passlib.utils.handlers.HasManyBackends.get_backend()` method.
+ but it can be set to ``2`` to use the older (and less secure)
+ version of the BCrypt algorithm.
+
+ .. versionchanged:: 1.6
+ This class now supports ``2y`` hashes, and recognizes
+ (but does not support) the broken ``2x`` hashes.
+ (see the :ref:`crypt_blowfish bug <crypt-blowfish-bug>`
+ for details).
"""
#=========================================================
diff --git a/passlib/handlers/cisco.py b/passlib/handlers/cisco.py
index c61a105..b6c4f6d 100644
--- a/passlib/handlers/cisco.py
+++ b/passlib/handlers/cisco.py
@@ -29,9 +29,10 @@ class cisco_pix(uh.HasUserContext, uh.StaticHandler):
It has a single round, and relies on the username
as the salt.
- The :meth:`encrypt()`, :meth:`genhash()`, and :meth:`verify()` methods
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt`, :meth:`~passlib.utils.handlers.PasswordHash.genhash`, and :meth:`~passlib.utils.handlers.PasswordHash.verify` methods
have the following extra keyword:
+ :type user: str
:param user:
String containing name of user account this password is associated with.
@@ -93,15 +94,20 @@ class cisco_type7(uh.GenericHandler):
It has a simple 4-5 bit salt, but is nonetheless a reversible encoding
instead of a real hash.
- The :meth:`encrypt` and :meth:`genhash` methods
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genhash` methods
have the following optional keyword:
+ :type salt: int
:param salt:
This may be an optional salt integer drawn from ``range(0,16)``.
If omitted, one will be chosen at random.
Note that while this class outputs digests in upper-case hexidecimal,
it will accept lower-case as well.
+
+ This class also provides the following additional method:
+
+ .. automethod:: decode
"""
#=========================================================
# class attrs
@@ -110,6 +116,7 @@ class cisco_type7(uh.GenericHandler):
setting_kwds = ("salt",)
checksum_chars = uh.UPPER_HEX_CHARS
+ min_salt_value = 0
max_salt_value = 52
#=========================================================
diff --git a/passlib/handlers/des_crypt.py b/passlib/handlers/des_crypt.py
index 68ab3dd..e738f6e 100644
--- a/passlib/handlers/des_crypt.py
+++ b/passlib/handlers/des_crypt.py
@@ -108,19 +108,13 @@ class des_crypt(uh.HasManyBackends, uh.HasSalt, uh.GenericHandler):
It supports a fixed-length salt.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: str
:param salt:
Optional salt string.
If not specified, one will be autogenerated (this is recommended).
If specified, it must be 2 characters, drawn from the regexp range ``[./0-9A-Za-z]``.
-
- It will use the first available of two possible backends:
-
- * stdlib :func:`crypt()`, if the host OS supports des-crypt (most unix systems).
- * a pure python implementation of des-crypt
-
- You can see which backend is in use by calling the :meth:`get_backend()` method.
"""
#=========================================================
# class attrs
@@ -192,23 +186,22 @@ class bsdi_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandler
It supports a fixed-length salt, and a variable number of rounds.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: str
:param salt:
Optional salt string.
If not specified, one will be autogenerated (this is recommended).
If specified, it must be 4 characters, drawn from the regexp range ``[./0-9A-Za-z]``.
+ :type rounds: int
:param rounds:
Optional number of rounds to use.
- Defaults to 5000, must be between 0 and 16777215, inclusive.
-
- It will use the first available of two possible backends:
-
- * stdlib :func:`crypt()`, if the host OS supports bsdi-crypt (most BSD systems).
- * a pure python implementation of bsdi-crypt
+ Defaults to 5001, must be between 1 and 16777215, inclusive.
- You can see which backend is in use by calling the :meth:`get_backend()` method.
+ .. versionchanged:: 1.6
+ :meth:`encrypt` will now issue a warning if an even number of rounds is used
+ (see :ref:`bsdi-crypt-security-issues` regarding weak DES keys).
"""
#=========================================================
# class attrs
@@ -324,8 +317,9 @@ class bigcrypt(uh.HasSalt, uh.GenericHandler):
It supports a fixed-length salt.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: str
:param salt:
Optional salt string.
If not specified, one will be autogenerated (this is recommended).
@@ -396,8 +390,9 @@ class crypt16(uh.HasSalt, uh.GenericHandler):
It supports a fixed-length salt.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: str
:param salt:
Optional salt string.
If not specified, one will be autogenerated (this is recommended).
diff --git a/passlib/handlers/django.py b/passlib/handlers/django.py
index 35d66f9..b7b22ce 100644
--- a/passlib/handlers/django.py
+++ b/passlib/handlers/django.py
@@ -93,16 +93,27 @@ class django_salted_sha1(DjangoSaltedHash):
It supports a variable-length salt, and uses a single round of SHA1.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: str
:param salt:
Optional salt string.
- If not specified, a 5 character one will be autogenerated (this is recommended).
- If specified, may be any series of characters drawn from the regexp range ``[0-9a-f]``.
+ If not specified, a 12 character one will be autogenerated (this is recommended).
+ If specified, may be any series of characters drawn from the regexp range ``[0-9a-zA-Z]``.
+ :type salt_size: int
:param salt_size:
Optional number of characters to use when autogenerating new salts.
- Defaults to 5, but can be any non-negative value.
+ Defaults to 12, but can be any positive value.
+
+ This should be compatible with Django 1.4's :class:`!SHA1PasswordHasher` class.
+
+ .. versionchanged: 1.6
+ This class now generates 12-character salts instead of 5,
+ and generated salts uses the character range ``[0-9a-zA-Z]`` instead of
+ the ``[0-9a-f]``. This is to be compatible with how Django >= 1.4
+ generates these hashes; but hashes generated in this manner will still be
+ correctly interpreted by earlier versions of Django.
"""
name = "django_salted_sha1"
django_name = "sha1"
@@ -119,16 +130,28 @@ class django_salted_md5(DjangoSaltedHash):
It supports a variable-length salt, and uses a single round of MD5.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: str
:param salt:
Optional salt string.
- If not specified, a 5 character one will be autogenerated (this is recommended).
- If specified, may be any series of characters drawn from the regexp range ``[0-9a-f]``.
+ If not specified, a 12 character one will be autogenerated (this is recommended).
+ If specified, may be any series of characters drawn from the regexp range ``[0-9a-zA-Z]``.
+ :type salt_size: int
:param salt_size:
Optional number of characters to use when autogenerating new salts.
- Defaults to 5, but can be any non-negative value.
+ Defaults to 12, but can be any positive value.
+
+ This should be compatible with the hashes generated by
+ Django 1.4's :class:`!MD5PasswordHasher` class.
+
+ .. versionchanged: 1.6
+ This class now generates 12-character salts instead of 5,
+ and generated salts uses the character range ``[0-9a-zA-Z]`` instead of
+ the ``[0-9a-f]``. This is to be compatible with how Django >= 1.4
+ generates these hashes; but hashes generated in this manner will still be
+ correctly interpreted by earlier versions of Django.
"""
name = "django_salted_md5"
django_name = "md5"
@@ -164,17 +187,20 @@ class django_pbkdf2_sha256(DjangoVariableHash):
It supports a variable-length salt, and a variable number of rounds.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: str
:param salt:
Optional salt string.
If not specified, a 12 character one will be autogenerated (this is recommended).
If specified, may be any series of characters drawn from the regexp range ``[0-9a-zA-Z]``.
+ :type salt_size: int
:param salt_size:
Optional number of characters to use when autogenerating new salts.
Defaults to 12, but can be any positive value.
+ :type rounds: int
:param rounds:
Optional number of rounds to use.
Defaults to 10000, but must be within ``range(1,1<<32)``.
@@ -206,17 +232,20 @@ class django_pbkdf2_sha1(django_pbkdf2_sha256):
It supports a variable-length salt, and a variable number of rounds.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: str
:param salt:
Optional salt string.
If not specified, a 12 character one will be autogenerated (this is recommended).
If specified, may be any series of characters drawn from the regexp range ``[0-9a-zA-Z]``.
+ :type salt_size: int
:param salt_size:
Optional number of characters to use when autogenerating new salts.
Defaults to 12, but can be any positive value.
+ :type rounds: int
:param rounds:
Optional number of rounds to use.
Defaults to 10000, but must be within ``range(1,1<<32)``.
@@ -240,8 +269,9 @@ class django_des_crypt(uh.HasSalt, uh.GenericHandler):
It supports a fixed-length salt.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: str
:param salt:
Optional salt string.
If not specified, one will be autogenerated (this is recommended).
diff --git a/passlib/handlers/fshp.py b/passlib/handlers/fshp.py
index 28be83c..1826344 100644
--- a/passlib/handlers/fshp.py
+++ b/passlib/handlers/fshp.py
@@ -29,7 +29,7 @@ class fshp(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler):
It supports a variable-length salt, and a variable number of rounds.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
:param salt:
Optional raw salt string.
@@ -41,7 +41,7 @@ class fshp(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler):
:param rounds:
Optional number of rounds to use.
- Defaults to 40000, must be between 1 and 4294967295, inclusive.
+ Defaults to 50000, must be between 1 and 4294967295, inclusive.
:param variant:
Optionally specifies variant of FSHP to use.
diff --git a/passlib/handlers/ldap_digests.py b/passlib/handlers/ldap_digests.py
index f51e482..a339486 100644
--- a/passlib/handlers/ldap_digests.py
+++ b/passlib/handlers/ldap_digests.py
@@ -107,7 +107,7 @@ class _SaltedBase64DigestHelper(uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHand
class ldap_md5(_Base64DigestHelper):
"""This class stores passwords using LDAP's plain MD5 format, and follows the :ref:`password-hash-api`.
- The :meth:`encrypt()` and :meth:`genconfig` methods have no optional keywords.
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods have no optional keywords.
"""
name = "ldap_md5"
setting_kwds = ()
@@ -119,7 +119,7 @@ class ldap_md5(_Base64DigestHelper):
class ldap_sha1(_Base64DigestHelper):
"""This class stores passwords using LDAP's plain SHA1 format, and follows the :ref:`password-hash-api`.
- The :meth:`encrypt()` and :meth:`genconfig` methods have no optional keywords.
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods have no optional keywords.
"""
name = "ldap_sha1"
setting_kwds = ()
@@ -133,18 +133,23 @@ class ldap_salted_md5(_SaltedBase64DigestHelper):
It supports a 4-16 byte salt.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keyword:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keyword:
+ :type salt: bytes
:param salt:
Optional salt string.
If not specified, one will be autogenerated (this is recommended).
If specified, it may be any 4-16 byte string.
+ :type salt_size: int
:param salt_size:
Optional number of bytes to use when autogenerating new salts.
Defaults to 4 bytes for compatibility with the LDAP spec,
but some systems use larger salts, and Passlib supports
any value between 4-16.
+
+ .. versionchanged:: 1.6
+ This format now supports variable length salts, instead of a fix 4 bytes.
"""
name = "ldap_salted_md5"
ident = u("{SMD5}")
@@ -158,18 +163,23 @@ class ldap_salted_sha1(_SaltedBase64DigestHelper):
It supports a 4-16 byte salt.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keyword:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keyword:
+ :type salt: bytes
:param salt:
Optional salt string.
If not specified, one will be autogenerated (this is recommended).
If specified, it may be any 4-16 byte string.
+ :type salt_size: int
:param salt_size:
Optional number of bytes to use when autogenerating new salts.
Defaults to 4 bytes for compatibility with the LDAP spec,
but some systems use larger salts, and Passlib supports
any value between 4-16.
+
+ .. versionchanged:: 1.6
+ This format now supports variable length salts, instead of a fix 4 bytes.
"""
name = "ldap_salted_sha1"
ident = u("{SSHA}")
@@ -185,7 +195,18 @@ class ldap_plaintext(plaintext):
except that it will identify a hash only if it does NOT begin with the ``{XXX}`` identifier prefix
used by RFC2307 passwords.
- Unicode passwords will be encoded using utf-8.
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt`, :meth:`~passlib.utils.handlers.PasswordHash.genhash`, and :meth:`~passlib.utils.handlers.PasswordHash.verify` methods all require the
+ following additional contextual keyword:
+
+ :type encoding: str
+ :param encoding:
+ This controls the character encoding to use (defaults to ``utf-8``).
+
+ This encoding will be used to encode :class:`!unicode` passwords
+ under Python 2, and decode :class:`!bytes` hashes under Python 3.
+
+ .. versionchanged:: 1.6
+ The ``encoding`` keyword was added.
"""
# NOTE: this subclasses plaintext, since all it does differently
# is override identify()
diff --git a/passlib/handlers/md5_crypt.py b/passlib/handlers/md5_crypt.py
index c963155..a3fdd9d 100644
--- a/passlib/handlers/md5_crypt.py
+++ b/passlib/handlers/md5_crypt.py
@@ -227,19 +227,13 @@ class md5_crypt(uh.HasManyBackends, _MD5_Common):
It supports a variable-length salt.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: str
:param salt:
Optional salt string.
If not specified, one will be autogenerated (this is recommended).
If specified, it must be 0-8 characters, drawn from the regexp range ``[./0-9A-Za-z]``.
-
- It will use the first available of two possible backends:
-
- * stdlib :func:`crypt()`, if the host OS supports MD5-Crypt.
- * a pure python implementation of MD5-Crypt built into passlib.
-
- You can see which backend is in use by calling the :meth:`get_backend()` method.
"""
#=========================================================
# class attrs
@@ -282,8 +276,9 @@ class apr_md5_crypt(_MD5_Common):
It supports a variable-length salt.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: str
:param salt:
Optional salt string.
If not specified, one will be autogenerated (this is recommended).
diff --git a/passlib/handlers/misc.py b/passlib/handlers/misc.py
index 2b26b12..30ddcef 100644
--- a/passlib/handlers/misc.py
+++ b/passlib/handlers/misc.py
@@ -26,12 +26,6 @@ __all__ = [
class unix_fallback(uh.StaticHandler):
"""This class provides the fallback behavior for unix shadow files, and follows the :ref:`password-hash-api`.
- .. note::
-
- This class has been deprecated as of Passlib 1.6,
- and will be removed in Passlib 1.8.
- Use 'unix_disabled' instead.
-
This class does not implement a hash, but instead provides fallback
behavior as found in /etc/shadow on most unix variants.
If used, should be the last scheme in the context.
@@ -42,6 +36,10 @@ class unix_fallback(uh.StaticHandler):
* by default it rejects all passwords if the hash is an empty string,
but if ``enable_wildcard=True`` is passed to verify(),
all passwords will be allowed through if the hash is an empty string.
+
+ .. deprecated:: 1.6
+ This has been deprecated due to it's "wildcard" feature,
+ and will be removed in Passlib 1.8. Use :class:`unix_disabled` instead.
"""
name = "unix_fallback"
context_kwds = ("enable_wildcard",)
@@ -90,8 +88,9 @@ class unix_disabled(uh.PasswordHash):
* "encrypting" a password will simply return the disabled account marker.
* it will reject all passwords, no matter the hash.
- The :meth:`encrypt` method supports one optional keyword:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` method supports one optional keyword:
+ :type marker: str
:param marker:
Optional marker string which overrides the platform default
used to indicate a disabled account.
@@ -99,6 +98,10 @@ class unix_disabled(uh.PasswordHash):
If not specified, this will default to ``*`` on BSD systems,
and use the Linux default ``!`` for all other platforms.
(:attr:`!unix_disabled.marker` will contain the default value)
+
+ .. versionadded:: 1.6
+ This class was added as a replacement for the now-deprecated
+ :class:`unix_fallback` class, which had some undesirable features.
"""
name = "unix_disabled"
setting_kwds = ("marker",)
@@ -150,6 +153,9 @@ class unix_disabled(uh.PasswordHash):
class plaintext(uh.PasswordHash):
"""This class stores passwords in plaintext, and follows the :ref:`password-hash-api`.
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt`, :meth:`~passlib.utils.handlers.PasswordHash.genhash`, and :meth:`~passlib.utils.handlers.PasswordHash.verify` methods all require the
+ following additional contextual keyword:
+
:type encoding: str
:param encoding:
This controls the character encoding to use (defaults to ``utf-8``).
diff --git a/passlib/handlers/mssql.py b/passlib/handlers/mssql.py
index e46c665..608614f 100644
--- a/passlib/handlers/mssql.py
+++ b/passlib/handlers/mssql.py
@@ -105,8 +105,9 @@ class mssql2000(uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler):
It supports a fixed-length salt.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: bytes
:param salt:
Optional salt string.
If not specified, one will be autogenerated (this is recommended).
@@ -174,8 +175,9 @@ class mssql2005(uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler):
It supports a fixed-length salt.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: bytes
:param salt:
Optional salt string.
If not specified, one will be autogenerated (this is recommended).
diff --git a/passlib/handlers/mysql.py b/passlib/handlers/mysql.py
index 9cb4eeb..ef6759c 100644
--- a/passlib/handlers/mysql.py
+++ b/passlib/handlers/mysql.py
@@ -48,7 +48,7 @@ class mysql323(uh.StaticHandler):
It has no salt and a single fixed round.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept no optional keywords.
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept no optional keywords.
"""
#=========================================================
# class attrs
@@ -97,7 +97,7 @@ class mysql41(uh.StaticHandler):
It has no salt and a single fixed round.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept no optional keywords.
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept no optional keywords.
"""
#=========================================================
# class attrs
diff --git a/passlib/handlers/oracle.py b/passlib/handlers/oracle.py
index f7083bf..000644f 100644
--- a/passlib/handlers/oracle.py
+++ b/passlib/handlers/oracle.py
@@ -56,12 +56,11 @@ class oracle10(uh.HasUserContext, uh.StaticHandler):
It has no salt and a single fixed round.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept no optional keywords.
-
- The :meth:`encrypt()`, :meth:`genhash()`, and :meth:`verify()` methods all require the
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt`, :meth:`~passlib.utils.handlers.PasswordHash.genhash`, and :meth:`~passlib.utils.handlers.PasswordHash.verify` methods all require the
following additional contextual keywords:
- :param user: string containing name of oracle user account this password is associated with.
+ :type user: str
+ :param user: name of oracle user account this password is associated with.
"""
#=========================================================
# algorithm information
@@ -108,8 +107,9 @@ class oracle11(uh.HasSalt, uh.GenericHandler):
It supports a fixed-length salt.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: str
:param salt:
Optional salt string.
If not specified, one will be autogenerated (this is recommended).
diff --git a/passlib/handlers/pbkdf2.py b/passlib/handlers/pbkdf2.py
index 3269f8e..0d4bdae 100644
--- a/passlib/handlers/pbkdf2.py
+++ b/passlib/handlers/pbkdf2.py
@@ -46,7 +46,7 @@ class Pbkdf2DigestHandler(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.Gen
#--HasRounds--
default_rounds = None # set by subclass
min_rounds = 1
- max_rounds = 2**32-1
+ max_rounds = 0xffffffff # setting at 32-bit limit for now
rounds_cost = "linear"
#--this class--
@@ -103,17 +103,20 @@ def create_pbkdf2_hash(hash_name, digest_size, rounds=12000, ident=None, module=
It supports a variable-length salt, and a variable number of rounds.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: bytes
:param salt:
Optional salt bytes.
If specified, the length must be between 0-1024 bytes.
If not specified, a %(dsc)d byte salt will be autogenerated (this is recommended).
+ :type salt_size: int
:param salt_size:
Optional number of bytes to use when autogenerating new salts.
Defaults to 16 bytes, but can be any value between 0 and 1024.
+ :type rounds: int
:param rounds:
Optional number of rounds to use.
Defaults to %(dr)d, but must be within ``range(1,1<<32)``.
@@ -143,20 +146,23 @@ class cta_pbkdf2_sha1(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.Generic
It supports a variable-length salt, and a variable number of rounds.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: bytes
:param salt:
Optional salt bytes.
If specified, it may be any length.
If not specified, a one will be autogenerated (this is recommended).
+ :type salt_size: int
:param salt_size:
Optional number of bytes to use when autogenerating new salts.
Defaults to 16 bytes, but can be any value between 0 and 1024.
+ :type rounds: int
:param rounds:
Optional number of rounds to use.
- Defaults to 10000, must be within ``range(1,1<<32)``.
+ Defaults to 60000, must be within ``range(1,1<<32)``.
"""
#=========================================================
@@ -178,7 +184,7 @@ class cta_pbkdf2_sha1(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.Generic
#--HasRounds--
default_rounds = 60000
min_rounds = 1
- max_rounds = 2**32-1
+ max_rounds = 0xffffffff # setting at 32-bit limit for now
rounds_cost = "linear"
#=========================================================
@@ -229,20 +235,23 @@ class dlitz_pbkdf2_sha1(uh.HasRounds, uh.HasSalt, uh.GenericHandler):
It supports a variable-length salt, and a variable number of rounds.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: str
:param salt:
Optional salt string.
If specified, it may be any length, but must use the characters in the regexp range ``[./0-9A-Za-z]``.
If not specified, a 16 character salt will be autogenerated (this is recommended).
+ :type salt_size: int
:param salt_size:
Optional number of bytes to use when autogenerating new salts.
Defaults to 16 bytes, but can be any value between 0 and 1024.
+ :type rounds: int
:param rounds:
Optional number of rounds to use.
- Defaults to 10000, must be within ``range(1,1<<32)``.
+ Defaults to 60000, must be within ``range(1,1<<32)``.
"""
#=========================================================
@@ -265,7 +274,7 @@ class dlitz_pbkdf2_sha1(uh.HasRounds, uh.HasSalt, uh.GenericHandler):
#--HasRounds--
default_rounds = 60000
min_rounds = 1
- max_rounds = 2**32-1
+ max_rounds = 0xffffffff # setting at 32-bit limit for now
rounds_cost = "linear"
#=========================================================
@@ -315,8 +324,9 @@ class atlassian_pbkdf2_sha1(uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler)
It supports a fixed-length salt, and a fixed number of rounds.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keyword:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keyword:
+ :type salt: bytes
:param salt:
Optional salt bytes.
If specified, the length must be exactly 16 bytes.
@@ -363,20 +373,23 @@ class grub_pbkdf2_sha512(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.Gene
It supports a variable-length salt, and a variable number of rounds.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: bytes
:param salt:
Optional salt bytes.
If specified, the length must be between 0-1024 bytes.
If not specified, a 64 byte salt will be autogenerated (this is recommended).
+ :type salt_size: int
:param salt_size:
Optional number of bytes to use when autogenerating new salts.
Defaults to 64 bytes, but can be any value between 0 and 1024.
+ :type rounds: int
:param rounds:
Optional number of rounds to use.
- Defaults to 10000, but must be within ``range(1,1<<32)``.
+ Defaults to 12000, but must be within ``range(1,1<<32)``.
"""
name = "grub_pbkdf2_sha512"
setting_kwds = ("salt", "salt_size", "rounds")
@@ -393,7 +406,7 @@ class grub_pbkdf2_sha512(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.Gene
default_rounds = 12000
min_rounds = 1
- max_rounds = 2**32-1
+ max_rounds = 0xffffffff # setting at 32-bit limit for now
rounds_cost = "linear"
@classmethod
diff --git a/passlib/handlers/phpass.py b/passlib/handlers/phpass.py
index 00a4e33..9742743 100644
--- a/passlib/handlers/phpass.py
+++ b/passlib/handlers/phpass.py
@@ -32,23 +32,25 @@ class phpass(uh.HasManyIdents, uh.HasRounds, uh.HasSalt, uh.GenericHandler):
It supports a fixed-length salt, and a variable number of rounds.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: str
:param salt:
Optional salt string.
If not specified, one will be autogenerated (this is recommended).
If specified, it must be 8 characters, drawn from the regexp range ``[./0-9A-Za-z]``.
+ :type rounds: int
:param rounds:
Optional number of rounds to use.
- Defaults to 9, must be between 7 and 30, inclusive.
+ Defaults to 16, must be between 7 and 30, inclusive.
This value is logarithmic, the actual number of iterations used will be :samp:`2**{rounds}`.
+ :type ident: str
:param ident:
phpBB3 uses ``H`` instead of ``P`` for it's identifier,
this may be set to ``H`` in order to generate phpBB3 compatible hashes.
it defaults to ``P``.
-
"""
#=========================================================
diff --git a/passlib/handlers/postgres.py b/passlib/handlers/postgres.py
index b268905..55dc593 100644
--- a/passlib/handlers/postgres.py
+++ b/passlib/handlers/postgres.py
@@ -26,12 +26,11 @@ class postgres_md5(uh.HasUserContext, uh.StaticHandler):
It has no salt and a single fixed round.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept no optional keywords.
-
- The :meth:`encrypt()`, :meth:`genhash()`, and :meth:`verify()` methods all require the
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt`, :meth:`~passlib.utils.handlers.PasswordHash.genhash`, and :meth:`~passlib.utils.handlers.PasswordHash.verify` methods all require the
following additional contextual keywords:
- :param user: string containing name of postgres user account this password is associated with.
+ :type user: str
+ :param user: name of postgres user account this password is associated with.
"""
#=========================================================
# algorithm information
diff --git a/passlib/handlers/scram.py b/passlib/handlers/scram.py
index ef73cf4..fd2b332 100644
--- a/passlib/handlers/scram.py
+++ b/passlib/handlers/scram.py
@@ -33,22 +33,26 @@ class scram(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler):
It supports a variable-length salt, and a variable number of rounds.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: bytes
:param salt:
Optional salt bytes.
If specified, the length must be between 0-1024 bytes.
If not specified, a 12 byte salt will be autogenerated
(this is recommended).
+ :type salt_size: int
:param salt_size:
Optional number of bytes to use when autogenerating new salts.
Defaults to 12 bytes, but can be any value between 0 and 1024.
+ :type rounds: int
:param rounds:
Optional number of rounds to use.
Defaults to 6400, but must be within ``range(1,1<<32)``.
+ :type algs: list of strings
:param algs:
Specify list of digest algorithms to use.
@@ -120,9 +124,11 @@ class scram(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler):
def extract_digest_info(cls, hash, alg):
"""return (salt, rounds, digest) for specific hash algorithm.
+ :type hash: str
:arg hash:
:class:`!scram` hash stored for desired user
+ :type alg: str
:arg alg:
Name of digest algorithm (e.g. ``"sha-1"``) requested by client.
@@ -156,9 +162,11 @@ class scram(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler):
def extract_digest_algs(cls, hash, format="iana"):
"""Return names of all algorithms stored in a given hash.
+ :type hash: str
:arg hash:
The :class:`!scram` hash to parse
+ :type format: str
:param format:
This changes the naming convention used by the
returned algorithm names. By default the names
@@ -185,9 +193,16 @@ class scram(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler):
SaltedPassword := Hi(Normalize(password), salt, i)
- :arg password: password as unicode or utf-8 encoded bytes.
- :arg salt: raw salt as bytes.
+ :type password: unicode or utf-8 bytes
+ :arg password: password to run through digest
+
+ :type salt: bytes
+ :arg salt: raw salt data
+
+ :type rounds: int
:arg rounds: number of iterations.
+
+ :type alg: str
:arg alg: name of digest to use (e.g. ``"sha-1"``).
:returns:
diff --git a/passlib/handlers/sha1_crypt.py b/passlib/handlers/sha1_crypt.py
index 35dff46..c729552 100644
--- a/passlib/handlers/sha1_crypt.py
+++ b/passlib/handlers/sha1_crypt.py
@@ -29,27 +29,23 @@ class sha1_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandler
It supports a variable-length salt, and a variable number of rounds.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: str
:param salt:
Optional salt string.
If not specified, an 8 character one will be autogenerated (this is recommended).
If specified, it must be 0-64 characters, drawn from the regexp range ``[./0-9A-Za-z]``.
+ :type salt_size: int
:param salt_size:
Optional number of bytes to use when autogenerating new salts.
Defaults to 8 bytes, but can be any value between 0 and 64.
+ :type rounds: int
:param rounds:
Optional number of rounds to use.
Defaults to 40000, must be between 1 and 4294967295, inclusive.
-
- It will use the first available of two possible backends:
-
- * stdlib :func:`crypt()`, if the host OS supports sha1-crypt (NetBSD).
- * a pure python implementation of sha1-crypt
-
- You can see which backend is in use by calling the :meth:`get_backend()` method.
"""
#=========================================================
diff --git a/passlib/handlers/sha2_crypt.py b/passlib/handlers/sha2_crypt.py
index 2069892..82b6977 100644
--- a/passlib/handlers/sha2_crypt.py
+++ b/passlib/handlers/sha2_crypt.py
@@ -362,17 +362,20 @@ class sha256_crypt(_SHA2_Common):
It supports a variable-length salt, and a variable number of rounds.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: str
:param salt:
Optional salt string.
If not specified, one will be autogenerated (this is recommended).
If specified, it must be 0-16 characters, drawn from the regexp range ``[./0-9A-Za-z]``.
+ :type rounds: int
:param rounds:
Optional number of rounds to use.
- Defaults to 40000, must be between 1000 and 999999999, inclusive.
+ Defaults to 80000, must be between 1000 and 999999999, inclusive.
+ :type implicit_rounds: bool
:param implicit_rounds:
this is an internal option which generally doesn't need to be touched.
@@ -380,13 +383,6 @@ class sha256_crypt(_SHA2_Common):
when encoding it to a string; this is only permitted by the spec for rounds=5000,
and the flag is ignored otherwise. the spec requires the two different
encodings be preserved as they are, instead of normalizing them.
-
- It will use the first available of two possible backends:
-
- * stdlib :func:`crypt()`, if the host OS supports SHA256-Crypt.
- * a pure python implementation of SHA256-Crypt built into passlib.
-
- You can see which backend is in use by calling the :meth:`get_backend()` method.
"""
#=========================================================
# class attrs
@@ -416,17 +412,20 @@ class sha512_crypt(_SHA2_Common):
It supports a variable-length salt, and a variable number of rounds.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: str
:param salt:
Optional salt string.
If not specified, one will be autogenerated (this is recommended).
If specified, it must be 0-16 characters, drawn from the regexp range ``[./0-9A-Za-z]``.
+ :type rounds: int
:param rounds:
Optional number of rounds to use.
- Defaults to 40000, must be between 1000 and 999999999, inclusive.
+ Defaults to 60000, must be between 1000 and 999999999, inclusive.
+ :type implicit_rounds: bool
:param implicit_rounds:
this is an internal option which generally doesn't need to be touched.
@@ -434,13 +433,6 @@ class sha512_crypt(_SHA2_Common):
when encoding it to a string; this is only permitted by the spec for rounds=5000,
and the flag is ignored otherwise. the spec requires the two different
encodings be preserved as they are, instead of normalizing them.
-
- It will use the first available of two possible backends:
-
- * stdlib :func:`crypt()`, if the host OS supports SHA512-Crypt.
- * a pure python implementation of SHA512-Crypt built into passlib.
-
- You can see which backend is in use by calling the :meth:`get_backend()` method.
"""
#=========================================================
diff --git a/passlib/handlers/sun_md5_crypt.py b/passlib/handlers/sun_md5_crypt.py
index 0349dea..d5884cb 100644
--- a/passlib/handlers/sun_md5_crypt.py
+++ b/passlib/handlers/sun_md5_crypt.py
@@ -169,22 +169,26 @@ class sun_md5_crypt(uh.HasRounds, uh.HasSalt, uh.GenericHandler):
It supports a variable-length salt, and a variable number of rounds.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept the following optional keywords:
+ :type salt: str
:param salt:
Optional salt string.
If not specified, a salt will be autogenerated (this is recommended).
If specified, it must be drawn from the regexp range ``[./0-9A-Za-z]``.
+ :type salt_size: int
:param salt_size:
If no salt is specified, this parameter can be used to specify
the size (in characters) of the autogenerated salt.
It currently defaults to 8.
+ :type rounds: int
:param rounds:
Optional number of rounds to use.
Defaults to 5000, must be between 0 and 4294963199, inclusive.
+ :type bare_salt: bool
:param bare_salt:
Optional flag used to enable an alternate salt digest behavior
used by some hash strings in this scheme.
diff --git a/passlib/handlers/windows.py b/passlib/handlers/windows.py
index bb9fdac..a96ddc4 100644
--- a/passlib/handlers/windows.py
+++ b/passlib/handlers/windows.py
@@ -31,9 +31,10 @@ class lmhash(uh.HasEncodingContext, uh.StaticHandler):
It has no salt and a single fixed round.
- The :meth:`encrypt()` and :meth:`verify` methods accept a single
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.verify` methods accept a single
optional keyword:
+ :type encoding: str
:param encoding:
This specifies what character encoding LMHASH should use when
@@ -68,7 +69,9 @@ class lmhash(uh.HasEncodingContext, uh.StaticHandler):
def raw(cls, secret, encoding=None):
"""encode password using LANMAN hash algorithm.
- :arg secret: secret as unicode or utf-8 encoded bytes
+ :type secret: unicode or utf-8 encoded bytes
+ :arg secret: secret to hash
+ :type encoding: str
:arg encoding:
optional encoding to use for unicode inputs.
this defaults to ``cp437``, which is the
@@ -112,7 +115,7 @@ class nthash(uh.StaticHandler):
It has no salt and a single fixed round.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept no optional keywords.
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept no optional keywords.
Note that while this class outputs lower-case hexidecimal digests,
it will accept upper-case digests as well.
@@ -165,7 +168,7 @@ bsd_nthash = uh.PrefixWrapper("bsd_nthash", nthash, prefix="$3$$", ident="$3$$",
It has no salt and a single fixed round.
- The :meth:`encrypt()` and :meth:`genconfig` methods accept no optional keywords.
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt` and :meth:`~passlib.utils.handlers.PasswordHash.genconfig` methods accept no optional keywords.
""")
##class ntlm_pair(object):
@@ -215,9 +218,10 @@ class msdcc(uh.HasUserContext, uh.StaticHandler):
It has a fixed number of rounds, and uses the associated
username as the salt.
- The :meth:`encrypt()`, :meth:`genhash()`, and :meth:`verify()` methods
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt`, :meth:`~passlib.utils.handlers.PasswordHash.genhash`, and :meth:`~passlib.utils.handlers.PasswordHash.verify` methods
have the following optional keywords:
+ :type user: str
:param user:
String containing name of user account this password is associated with.
This is required to properly calculate the hash.
@@ -262,9 +266,10 @@ class msdcc2(uh.HasUserContext, uh.StaticHandler):
It has a fixed number of rounds, and uses the associated
username as the salt.
- The :meth:`encrypt()`, :meth:`genhash()`, and :meth:`verify()` methods
+ The :meth:`~passlib.utils.handlers.PasswordHash.encrypt`, :meth:`~passlib.utils.handlers.PasswordHash.genhash`, and :meth:`~passlib.utils.handlers.PasswordHash.verify` methods
have the following extra keyword:
+ :type user: str
:param user:
String containing name of user account this password is associated with.
This is required to properly calculate the hash.
@@ -287,7 +292,10 @@ class msdcc2(uh.HasUserContext, uh.StaticHandler):
def raw(cls, secret, user):
"""encode password using msdcc v2 algorithm
- :arg secret: secret as unicode or utf-8 encoded bytes
+ :type secret: unicode or utf-8 bytes
+ :arg secret: secret
+
+ :type user: str
:arg user: username to use as salt
:returns: returns string of raw bytes