The Passlib documentation has moved to https://passlib.readthedocs.io
passlib.utils.handlers
- Framework for writing password hashes¶
Warning
This module is primarily used as an internal support module. Its interface has not been finalized yet, and may be changed somewhat between major releases of Passlib, as the internal code is cleaned up and simplified.
Todo
This module, and the instructions on how to write a custom handler, definitely need to be rewritten for clarity. They are not yet organized, and may leave out some important details.
Implementing Custom Handlers¶
All that is required in order to write a custom handler that will work with Passlib is to create an object (be it module, class, or object) that exposes the functions and attributes required by the PasswordHash API. For classes, Passlib does not make any requirements about what a class instance should look like (if the implementation even uses them).
That said, most of the handlers built into Passlib are based around the GenericHandler
class, and its associated mixin classes. While deriving from this class is not required,
doing so will greatly reduce the amount of additional code that is needed for
all but the most convoluted password hash schemes.
Once a handler has been written, it may be used explicitly, passed into
a CryptContext
constructor, or registered
globally with Passlib via the passlib.registry
module.
See also
Testing Hash Handlers for details about how to test custom handlers against Passlib’s unittest suite.
The GenericHandler Class¶
Design¶
Most of the handlers built into Passlib are based around the GenericHandler
class. This class is designed under the assumption that the common
workflow for hashes is some combination of the following:
- parse hash into constituent parts - performed by
from_string()
. - validate constituent parts - performed by
GenericHandler
‘s constructor, and the normalization functions such as_norm_checksum()
and_norm_salt()
which are provided by its related mixin classes. - calculate the raw checksum for a specific password - performed by
_calc_checksum()
. - assemble hash, including new checksum, into a new string - performed by
to_string()
.
With this in mind, GenericHandler
provides implementations
of most of the PasswordHash API methods, eliminating the need
for almost all the boilerplate associated with writing a password hash.
In order to minimize the amount of unneeded features that must be loaded in, the GenericHandler
class itself contains only the parts which are needed by almost all handlers: parsing, rendering, and checksum validation.
Validation of all other parameters (such as salt, rounds, etc) is split out into separate
mixin classes which enhance GenericHandler
with additional features.
Usage¶
In order to use GenericHandler
, just subclass it, and then do the following:
fill out the
name
attribute with the name of your hash.fill out the
setting_kwds
attribute with a tuple listing all the settings your hash accepts.provide an implementation of the
from_string()
classmethod.this method should take in a potential hash string, parse it into components, and return an instance of the class which contains the parsed components. It should throw a
ValueError
if no hash, or an invalid hash, is provided.provide an implementation of the
to_string()
instance method.this method should render an instance of your handler class (such as returned by
from_string()
), returning a hash string.provide an implementation of the
_calc_checksum()
instance method.this is the heart of the hash; this method should take in the password as the first argument, then generate and return the digest portion of the hash, according to the settings (such as salt, etc) stored in the parsed instance this method was called from.
note that it should not return the full hash with identifiers, etc; that job should be performed by
to_string()
.
Some additional notes:
- In addition to simply subclassing
GenericHandler
, most handlers will also benefit from adding in some of the mixin classes that are designed to add features toGenericHandler
. See GenericHandler Mixins for more details.- Most implementations will want to alter/override the default
identify()
method. By default, it returnsTrue
for all hashes thatfrom_string()
can parse without raising aValueError
; which is reliable, but somewhat slow. For faster identification purposes, subclasses may fill in theident
attribute with the hash’s identifying prefix, whichidentify()
will then test for instead of callingfrom_string()
. For more complex situations, a custom implementation should be used; theHasManyIdents
mixin may also be helpful.- This class does not support context kwds of any type, since that is a rare enough requirement inside passlib.
Interface¶
-
class
passlib.utils.handlers.
GenericHandler
(checksum=None, use_defaults=False, **kwds)¶ helper class for implementing hash handlers.
GenericHandler-derived classes will have (at least) the following constructor options, though others may be added by mixins and by the class itself:
Parameters: - checksum – this should contain the digest portion of a
parsed hash (mainly provided when the constructor is called
by
from_string()
). defaults toNone
. - use_defaults –
If
False
(the default), aTypeError
should be thrown if any settings required by the handler were not explicitly provided.If
True
, the handler should attempt to provide a default for any missing values. This means generate missing salts, fill in default cost parameters, etc.This is typically only set to
True
when the constructor is called byhash()
, allowing user-provided values to be handled in a more permissive manner. - relaxed –
If
False
(the default), aValueError
should be thrown if any settings are out of bounds or otherwise invalid.If
True
, they should be corrected if possible, and a warning issue. If not possible, only then should an error be raised. (e.g. underrelaxed=True
, rounds values will be clamped to min/max rounds).This is mainly used when parsing the config strings of certain hashes, whose specifications implementations to be tolerant of incorrect values in salt strings.
Class Attributes¶
-
ident
¶ [optional] If this attribute is filled in, the default
identify()
method will use it as a identifying prefix that can be used to recognize instances of this handler’s hash. Filling this out is recommended for speed.This should be a unicode str.
-
_hash_regex
¶ [optional] If this attribute is filled in, the default
identify()
method will use it to recognize instances of the hash. Ifident
is specified, this will be ignored.This should be a unique regex object.
-
checksum_size
¶ [optional] Specifies the number of characters that should be expected in the checksum string. If omitted, no check will be performed.
-
checksum_chars
¶ [optional] A string listing all the characters allowed in the checksum string. If omitted, no check will be performed.
This should be a unicode str.
Instance Attributes¶
-
checksum
¶ The checksum string provided to the constructor (after passing it through
_norm_checksum()
).
Required Subclass Methods¶
The following methods must be provided by handler subclass:
-
classmethod
from_string
(hash, **context)¶ return parsed instance from hash/configuration string
Parameters: **context – context keywords to pass to constructor (if applicable). Raises: ValueError – if hash is incorrectly formatted Returns: hash parsed into components, for formatting / calculating checksum.
-
to_string
()¶ render instance to hash or configuration string
Returns: hash string with salt & digest included. should return native string type (ascii-bytes under python 2, unicode under python 3)
-
_calc_checksum
(secret)¶ given secret; calcuate and return encoded checksum portion of hash string, taking config from object state
calc checksum implementations may assume secret is always either unicode or bytes, checks are performed by verify/etc.
Default Methods¶
The following methods have default implementations that should work for most cases, though they may be overridden if the hash subclass needs to:
-
_norm_checksum
(checksum, relaxed=False)¶ validates checksum keyword against class requirements, returns normalized version of checksum.
-
classmethod
genconfig
(**kwds)¶
-
classmethod
genhash
(secret, config, **context)¶
-
classmethod
identify
(hash)¶
-
classmethod
hash
(secret, **kwds)¶
-
classmethod
verify
(secret, hash, **context)¶
- checksum – this should contain the digest portion of a
parsed hash (mainly provided when the constructor is called
by
GenericHandler Mixins¶
-
class
passlib.utils.handlers.
HasSalt
(salt=None, **kwds)¶ mixin for validating salts.
This
GenericHandler
mixin adds asalt
keyword to the class constuctor; any value provided is passed through the_norm_salt()
method, which takes care of validating salt length and content, as well as generating new salts if one it not provided.Parameters: - salt – optional salt string
- salt_size – optional size of salt (only used if no salt provided);
defaults to
default_salt_size
.
Class Attributes¶
In order for
_norm_salt()
to do its job, the following attributes should be provided by the handler subclass:-
min_salt_size
¶ The minimum number of characters allowed in a salt string. An
ValueError
will be throw if the provided salt is too small. Defaults to0
.
-
max_salt_size
¶ The maximum number of characters allowed in a salt string. By default an
ValueError
will be throw if the provided salt is too large; but ifrelaxed=True
, it will be clipped and a warning issued instead. Defaults toNone
, for no maximum.
-
default_salt_size
¶ [required] If no salt is provided, this should specify the size of the salt that will be generated by
_generate_salt()
. By default this will fall back tomax_salt_size
.
-
salt_chars
¶ A string containing all the characters which are allowed in the salt string. An
ValueError
will be throw if any other characters are encountered. May be set toNone
to skip this check (but see indefault_salt_chars
).
-
default_salt_chars
¶ [required] This attribute controls the set of characters use to generate new salt strings. By default, it mirrors
salt_chars
. Ifsalt_chars
isNone
, this attribute must be specified in order to generate new salts. Aside from that purpose, the main use of this attribute is for hashes which wish to generate salts from a restricted subset ofsalt_chars
; such as accepting all characters, but only using a-z.
Instance Attributes¶
-
salt
¶ This instance attribute will be filled in with the salt provided to the constructor (as adapted by
_norm_salt()
)
Subclassable Methods¶
-
classmethod
_norm_salt
(salt, relaxed=False)¶ helper to normalize & validate user-provided salt string
Parameters: salt – salt string
Raises: - TypeError – If salt not correct type.
- ValueError –
- if salt contains chars that aren’t in
salt_chars
. - if salt contains less than
min_salt_size
characters. - if
relaxed=False
and salt has more thanmax_salt_size
characters (ifrelaxed=True
, the salt is truncated and a warning is issued instead).
- if salt contains chars that aren’t in
Returns: normalized salt
-
classmethod
_generate_salt
()¶ helper method for _init_salt(); generates a new random salt string.
-
class
passlib.utils.handlers.
HasRounds
(rounds=None, **kwds)¶ mixin for validating rounds parameter
This
GenericHandler
mixin adds arounds
keyword to the class constuctor; any value provided is passed through the_norm_rounds()
method, which takes care of validating the number of rounds.Parameters: rounds – optional number of rounds hash should use Class Attributes¶
In order for
_norm_rounds()
to do its job, the following attributes must be provided by the handler subclass:-
min_rounds
¶ The minimum number of rounds allowed. A
ValueError
will be thrown if the rounds value is too small. Defaults to0
.
-
max_rounds
¶ The maximum number of rounds allowed. A
ValueError
will be thrown if the rounds value is larger than this. Defaults toNone
which indicates no limit to the rounds value.
-
default_rounds
¶ If no rounds value is provided to constructor, this value will be used. If this is not specified, a rounds value must be specified by the application.
-
rounds_cost
¶ [required] The
rounds
parameter typically encodes a cpu-time cost for calculating a hash. This should be set to"linear"
(the default) or"log2"
, depending on how the rounds value relates to the actual amount of time that will be required.
Class Methods¶
Todo
document using() and needs_update() options
Instance Attributes¶
-
rounds
¶ This instance attribute will be filled in with the rounds value provided to the constructor (as adapted by
_norm_rounds()
)
Subclassable Methods¶
-
classmethod
_norm_rounds
(rounds, relaxed=False, param='rounds')¶ helper for normalizing rounds value.
Parameters: - rounds – an integer cost parameter.
- relaxed – if
True
(the default), issues PasslibHashWarning is rounds are outside allowed range. ifFalse
, raises a ValueError instead. - param – optional name of parameter to insert into error/warning messages.
Raises: - TypeError –
- if
use_defaults=False
and no rounds is specified - if rounds is not an integer.
- if
- ValueError –
- if rounds is
None
and class does not specify a value fordefault_rounds
. - if
relaxed=False
and rounds is outside bounds ofmin_rounds
andmax_rounds
(ifrelaxed=True
, the rounds value will be clamped, and a warning issued).
- if rounds is
Returns: normalized rounds value
-
-
class
passlib.utils.handlers.
HasManyIdents
(ident=None, **kwds)¶ mixin for hashes which use multiple prefix identifiers
For the hashes which may use multiple identifier prefixes, this mixin adds an
ident
keyword to constructor. Any value provided is passed through thenorm_idents()
method, which takes care of validating the identifier, as well as allowing aliases for easier specification of the identifiers by the user.Todo
document this class’s usage
Class Methods¶
Todo
document using() and needs_update() options
-
class
passlib.utils.handlers.
HasManyBackends
(checksum=None, use_defaults=False, **kwds)¶ GenericHandler mixin which provides selecting from multiple backends.
Todo
finish documenting this class’s usage
For hashes which need to select from multiple backends, depending on the host environment, this class offers a way to specify alternate
_calc_checksum()
methods, and will dynamically chose the best one at runtime.Changed in version 1.7: This class now derives from
BackendMixin
, which abstracts out a more generic framework for supporting multiple backends. The public api (get_backend()
,has_backend()
,set_backend()
) is roughly the same.Private API (Subclass Hooks)¶
As of version 1.7, classes should implement
_load_backend_{name}()
, perBackendMixin
. This hook should invoke_set_calc_checksum_backcend()
to install it’s backend method.Deprecated since version 1.7: The following api is deprecated, and will be removed in Passlib 2.0:
-
_has_backend_{name}
private class attribute checked by
has_backend()
to see if a specific backend is available, it should be eitherTrue
orFalse
. One of these should be provided by the subclass for each backend listed inbackends
.
-
_calc_checksum_{name}
private class method that should implement
_calc_checksum()
for a given backend. it will only be called if the backend has been selected byset_backend()
. One of these should be provided by the subclass for each backend listed inbackends
.
-
-
class
passlib.utils.handlers.
HasRawSalt
(salt=None, **kwds)¶ mixin for classes which use decoded salt parameter
A variant of
HasSalt
which takes in decoded bytes instead of an encoded string.Todo
document this class’s usage
-
class
passlib.utils.handlers.
HasRawChecksum
(checksum=None, use_defaults=False, **kwds)¶ mixin for classes which work with decoded checksum bytes
Todo
document this class’s usage
Examples¶
Todo
Show some walk-through examples of how to use GenericHandler and its mixins
The StaticHandler class¶
-
class
passlib.utils.handlers.
StaticHandler
(checksum=None, use_defaults=False, **kwds)¶ GenericHandler mixin for classes which have no settings.
This mixin assumes the entirety of the hash ise stored in the
checksum
attribute; that the hash has no rounds, salt, etc. This class provides the following:- a default
genconfig()
that always returns None. - a default
from_string()
andto_string()
that store the entire hash withinchecksum
, after optionally stripping a constant prefix.
All that is required by subclasses is an implementation of the
_calc_checksum()
method.- a default
Todo
Show some examples of how to use StaticHandler
Other Constructors¶
-
class
passlib.utils.handlers.
PrefixWrapper
(name, wrapped, prefix='', orig_prefix='', lazy=False, doc=None, ident=None)¶ wraps another handler, adding a constant prefix.
instances of this class wrap another password hash handler, altering the constant prefix that’s prepended to the wrapped handlers’ hashes.
this is used mainly by the ldap crypt handlers; such as
ldap_md5_crypt
which wrapsmd5_crypt
and adds a{CRYPT}
prefix.usage:
myhandler = PrefixWrapper("myhandler", "md5_crypt", prefix="$mh$", orig_prefix="$1$")
Parameters: - name – name to assign to handler
- wrapped – handler object or name of registered handler
- prefix – identifying prefix to prepend to all hashes
- orig_prefix – prefix to strip (defaults to ‘’).
- lazy – if True and wrapped handler is specified by name, don’t look it up until needed.
Testing Hash Handlers¶
Within its unittests, Passlib provides the HandlerCase
class,
which can be subclassed to provide a unittest-compatible test class capable of
checking if a handler adheres to the PasswordHash API.
Usage¶
As an example of how to use HandlerCase
,
the following is an annotated version
of the unittest for passlib.hash.des_crypt
:
from passlib.hash import des_crypt
from passlib.tests.utils import HandlerCase
# create a subclass for the handler...
class DesCryptTest(HandlerCase):
"test des-crypt algorithm"
# [required] - store the handler object itself in the handler attribute
handler = des_crypt
# [required] - this should be a list of (password, hash) pairs,
# which should all verify correctly using your handler.
# it is recommend include pairs which test all of the following:
#
# * empty string & short strings for passwords
# * passwords with 2 byte unicode characters
# * hashes with varying salts, rounds, and other options
known_correct_hashes = (
# format: (password, hash)
('', 'OgAwTx2l6NADI'),
(' ', '/Hk.VPuwQTXbc'),
('test', 'N1tQbOFcM5fpg'),
('Compl3X AlphaNu3meric', 'um.Wguz3eVCx2'),
('4lpHa N|_|M3r1K W/ Cur5Es: #$%(*)(*%#', 'sNYqfOyauIyic'),
('AlOtBsOl', 'cEpWz5IUCShqM'),
(u'hell\u00D6', 'saykDgk3BPZ9E'),
)
# [optional] - if there are hashes which are similar in format
# to your handler, and you want to make sure :meth:`identify`
# does not return ``True`` for such hashes,
# list them here. otherwise this can be omitted.
#
known_unidentified_hashes = [
# bad char in otherwise correctly formatted hash
'!gAwTx2l6NADI',
]
Interface¶
-
class
passlib.tests.utils.
HandlerCase
¶ base class for testing password hash handlers (esp passlib.utils.handlers subclasses)
In order to use this to test a handler, create a subclass will all the appropriate attributes filled as listed in the example below, and run the subclass via unittest.
Todo
Document all of the options HandlerCase offers.
Note
This is subclass of
unittest.TestCase
(orunittest2.TestCase
if available).