summaryrefslogtreecommitdiff
path: root/docs/lib/passlib.context.rst
blob: 5ed7413c907f462098bae46e4d8dcd186906a6de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
.. index:: CryptContext; reference

.. module:: passlib.context
    :synopsis: CryptContext class, for managing multiple password hash schemes

.. _context-reference:

======================================================
:mod:`passlib.context` - CryptContext Hash Manager
======================================================
This page provides a complete reference of all the methods
and options supported by the :class:`!CryptContext` class
and helper utilities.

.. seealso::

    * :ref:`context-tutorial` --
      overview of this class and walkthrough of how to use it.

.. rst-class:: emphasize-children toc-always-open

The CryptContext Class
======================
.. class:: CryptContext(schemes=None, \*\*kwds)

    Helper for hashing passwords using different algorithms.

    At its base, this is a proxy object that makes it easy to use
    multiple :class:`~passlib.ifc.PasswordHash` objects at the same time.
    Instances of this class can be created by calling the constructor
    with the appropriate keywords, or by using one of the alternate
    constructors, which can load directly from a string or a local file.
    Since this class has so many options and methods, they have been broken
    out into subsections:

    * `Constructor Keywords`_ -- all the keywords this class accepts.
        - `Context Options`_ -- options affecting the Context itself.
        - `Algorithm Options`_ -- options controlling the wrapped hashes.
    * `Primary Methods`_ -- the primary methods most applications need.
    * `Hash Migration`_ -- methods for automatically replacing deprecated hashes.
    * `Alternate Constructors`_ -- creating instances from strings or files.
    * `Changing the Configuration`_ -- altering the configuration of an existing context.
    * `Examining the Configuration`_ -- programmatically examining the context's settings.
    * `Saving the Configuration`_ -- exporting the context's current configuration.
    * `Configuration Errors`_ -- overview of errors that may be thrown by :class:`!CryptContext` constructor

.. index:: CryptContext; keyword options

.. rst-class:: html-toggle expanded toc-always-open

Constructor Keywords
--------------------
The :class:`CryptContext` class accepts the following keywords,
all of which are optional.
The keywords are divided into two categories: `context options`_, which affect
the CryptContext itself; and `algorithm options`_, which place defaults
and limits on the algorithms used by the CryptContext.

.. _context-options:

Context Options
...............
Options which directly affect the behavior of the CryptContext instance:

.. _context-schemes-option:

``schemes``
    List of algorithms which the instance should support.

    The most important option in the constructor,
    This option controls what hashes can be used
    by the :meth:`~CryptContext.hash` method,
    which hashes will be recognized by :meth:`~CryptContext.verify`
    and :meth:`~CryptContext.identify`, and other effects
    throughout the instance.
    It should be a sequence of names,
    drawn from the hashes in :mod:`passlib.hash`.
    Listing an unknown name will cause a :exc:`ValueError`.
    You can use the :meth:`~CryptContext.schemes` method
    to get a list of the currently configured algorithms.
    As an example, the following creates a CryptContext instance
    which supports the :class:`~passlib.hash.sha256_crypt` and
    :class:`~passlib.hash.des_crypt` schemes::

        >>> from passlib.context import CryptContext
        >>> myctx = CryptContext(schemes=["sha256_crypt", "des_crypt"])
        >>> myctx.schemes()
        ("sha256_crypt", "des_crypt")


    .. note::

        The order of the schemes is sometimes important,
        as :meth:`~CryptContext.identify` will run
        through the schemes from first to last until an algorithm
        "claims" the hash. So plaintext algorithms and
        the like should be listed at the end.

    .. seealso:: the :ref:`context-basic-example` example in the tutorial.

.. _context-default-option:

``default``
    Specifies the name of the default scheme.

    This option controls which of the configured
    schemes will be used as the default when creating
    new hashes. This parameter is optional; if omitted,
    the first non-deprecated algorithm in ``schemes`` will be used.
    You can use the :meth:`~CryptContext.default_scheme` method
    to retrieve the name of the current default scheme.
    As an example, the following demonstrates the effect
    of this parameter on the :meth:`~CryptContext.hash`
    method::

        >>> from passlib.context import CryptContext
        >>> myctx = CryptContext(schemes=["sha256_crypt", "md5_crypt"])

        >>> # hash() uses the first scheme
        >>> myctx.default_scheme()
        'sha256_crypt'
        >>> myctx.hash("password")
        '$5$rounds=80000$R5ZIZRTNPgbdcWq5$fT/Oeqq/apMa/0fbx8YheYWS6Z3XLTxCzEtutsk2cJ1'

        >>> # but setting default causes the second scheme to be used.
        >>> myctx.update(default="md5_crypt")
        >>> myctx.default_scheme()
        'md5_crypt'
        >>> myctx.hash("password")
        '$1$Rr0C.KI8$Kvciy8pqfL9BQ2CJzEzfZ/'

    .. seealso:: the :ref:`context-basic-example` example in the tutorial.

.. _context-deprecated-option:

``deprecated``
    List of algorithms which should be considered "deprecated".

    This has the same format as ``schemes``, and should be
    a subset of those algorithms. The main purpose of this
    method is to flag schemes which need to be rehashed
    when the user next logs in. This has no effect
    on the `Primary Methods`_; but if the special `Hash Migration`_
    methods are passed a hash belonging to a deprecated scheme,
    they will flag it as needed to be rehashed using
    the ``default`` scheme.

    This may also contain a single special value,
    ``["auto"]``, which will configure the CryptContext instance
    to deprecate *all* supported schemes except for the default scheme.

    .. versionadded:: 1.6
        Added support for the ``["auto"]`` value.

    .. seealso:: :ref:`context-migration-example` in the tutorial

:samp:`truncate_error`

    By default, some algorithms will truncate large passwords
    (e.g. :class:`~passlib.hash.bcrypt` truncates ones larger than 72 bytes).
    Such hashes accept a ``truncate_error=True`` option to make them
    raise a :exc:`~passlib.exc.PasswordTruncateError` instead.

    This can also be set at the CryptContext level,
    and will passed to all hashes that support it.

    .. versionadded:: 1.7

.. _context-min-verify-time-option:

``min_verify_time``

    If specified, unsuccessful :meth:`~CryptContext.verify`
    calls will be penalized, and take at least this may
    seconds before the method returns. May be an integer
    or fractional number of seconds.

    .. deprecated:: 1.6
        This option has not proved very useful, is ignored by 1.7,
        and will be removed in version 1.8.

    .. versionchanged:: 1.7

        Per deprecation roadmap above, this option is now ignored.

.. _context-harden-verify-option:

``harden_verify``

    Companion to ``min_verify_time``, currently ignored.

    .. versionadded:: 1.7

    .. deprecated:: 1.7.1

        This option is ignored by 1.7.1, and will be removed in 1.8
        along with ``min_verify_time``.

.. _context-algorithm-options:

Algorithm Options
.................
All of the other options that can be passed to a :class:`CryptContext`
constructor affect individual hash algorithms.
All of the following keys have the form :samp:`{scheme}__{key}`,
where :samp:`{scheme}` is the name of one of the algorithms listed
in ``schemes``, and :samp:`{option}` one of the parameters below:

.. _context-default-rounds-option:

:samp:`{scheme}__rounds`

    Set the number of rounds required for this scheme
    when generating new hashes (using :meth:`~CryptContext.hash`).
    Existing hashes which have a different number of rounds will be marked
    as deprecated.

    This essentially sets ``default_rounds``, ``min_rounds``, and ``max_rounds`` all at once.
    If any of those options are also specified, they will override the value specified
    by ``rounds``.

    .. versionadded:: 1.7

        Previous releases of Passlib treated this as an alias for ``default_rounds``.

:samp:`{scheme}__default_rounds`

    Sets the default number of rounds to use with this scheme
    when generating new hashes (using :meth:`~CryptContext.hash`).

    If not set, this will fall back to the an algorithm-specific
    :attr:`~passlib.ifc.PasswordHash.default_rounds`.
    For hashes which do not support a rounds parameter, this option is ignored.
    As an example::

        >>> from passlib.context import CryptContext

        >>> # no explicit default_rounds set, so hash() uses sha256_crypt's default (80000)
        >>> myctx = CryptContext(["sha256_crypt"])
        >>> myctx.hash("fooey")
        '$5$rounds=80000$60Y7mpmAhUv6RDvj$AdseAOq6bKUZRDRTr/2QK1t38qm3P6sYeXhXKnBAmg0'
                   ^^^^^

        >>> # but if a default is specified, it will be used instead.
        >>> myctx = CryptContext(["sha256_crypt"], sha256_crypt__default_rounds=77123)
        >>> myctx.hash("fooey")
        '$5$rounds=77123$60Y7mpmAhUv6RDvj$AdseAOq6bKUZRDRTr/2QK1t38qm3P6sYeXhXKnBAmg0'
                   ^^^^^

    .. seealso:: the :ref:`context-default-settings-example` example in the tutorial.

:samp:`{scheme}__vary_rounds`

    .. deprecated:: 1.7

        This option has been deprecated as of Passlib 1.7, and will be removed in Passlib 2.0.
        The (very minimal) security benefit it provides was judged to not be worth code complexity
        it requires.

    Instead of using a fixed rounds value (such as specified by
    ``default_rounds``, above); this option will cause each call
    to :meth:`~CryptContext.hash` to vary the default rounds value
    by some amount.

    This can be an integer value, in which case each call will use a rounds
    value within the range ``default_rounds +/- vary_rounds``. It may
    also be a floating point value within the range 0.0 .. 1.0,
    in which case the range will be calculated as a proportion of the
    current default rounds (``default_rounds +/- default_rounds*vary_rounds``).
    A typical setting is ``0.1`` to ``0.2``.

    As an example of how this parameter operates::

        >>> # without vary_rounds set, hash() uses the same amount each time:
        >>> from passlib.context import CryptContext
        >>> myctx = CryptContext(schemes=["sha256_crypt"],
        ...                      sha256_crypt__default_rounds=80000)
        >>> myctx.hash("fooey")
        '$5$rounds=80000$60Y7mpmAhUv6RDvj$AdseAOq6bKUZRDRTr/2QK1t38qm3P6sYeXhXKnBAmg0'
        >>> myctx.hash("fooey")
        '$5$rounds=80000$60Y7mpmAhUv6RDvj$AdseAOq6bKUZRDRTr/2QK1t38qm3P6sYeXhXKnBAmg0'
                   ^^^^^

        >>> # but if vary_rounds is set, each one will be randomized
        >>> # (in this case, within the range 72000 .. 88000)
        >>> myctx = CryptContext(schemes=["sha256_crypt"],
        ...                      sha256_crypt__default_rounds=80000,
        ...                      sha256_crypt__vary_rounds=0.1)
        >>> myctx.hash("fooey")
        '$5$rounds=83966$bMpgQxN2hXo2kVr4$jL4Q3ov41UPgSbO7jYL0PdtsOg5koo4mCa.UEF3zan.'
        >>> myctx.hash("fooey")
        '$5$rounds=72109$43BBHC/hYPHzL69c$VYvVIdKn3Zdnvu0oJHVlo6rr0WjiMTGmlrZrrH.GxnA'
                   ^^^^^

    .. note::

        This is not a *needed* security measure, but it lets some of the less-significant
        digits of the rounds value act as extra salt bits; and helps foil
        any attacks targeted at a specific number of rounds of a hash.

.. _context-min-rounds-option:
.. _context-max-rounds-option:

:samp:`{scheme}__min_rounds`,
:samp:`{scheme}__max_rounds`

    These options place a limit on the number of rounds allowed for a particular
    scheme.

    For one, they limit what values are allowed for ``default_rounds``,
    and clip the effective range of the ``vary_rounds`` parameter.
    More importantly though, they proscribe a minimum strength for the hash,
    and any hashes which don't have sufficient rounds will be flagged as
    needing rehashing by the `Hash Migration`_ methods.

    .. note::

        These are configurable per-context limits.
        A warning will be issued if they exceed any hard limits
        set by the algorithm itself.

    .. seealso:: the :ref:`context-min-rounds-example` example in the tutorial.

.. _context-other-option:

:samp:`{scheme}__{other-option}`

    Finally, any other options are assumed to correspond to one of the
    that algorithm's :meth:`!hash` :attr:`settings <~passlib.ifc.PasswordHash.setting_kwds>`,
    such as setting a ``salt_size``.

    .. seealso:: the :ref:`context-default-settings-example` example in the tutorial.

Global Algorithm Options
........................
:samp:`all__{option}`

    The special scheme ``all`` permits you to set an option, and have
    it act as a global default for all the algorithms in the context.
    For instance, ``all__vary_rounds=0.1`` would set the ``vary_rounds``
    option for all the schemes where it was not overridden with an
    explicit :samp:`{scheme}__vary_rounds` option.

    .. deprecated:: 1.7

        This special scheme is deprecated as of Passlib 1.7, and will be removed in Passlib 2.0.
        It's only legitimate use was for ``vary_rounds``, which is also being removed in Passlib 2.0.

.. _user-categories:

.. rst-class:: html-toggle

User Categories
...............
:samp:`{category}__context__{option}`,
:samp:`{category}__{scheme}__{option}`

    Passing keys with this format to the :class:`CryptContext` constructor
    allows you to specify conditional context and algorithm options,
    controlled by the ``category`` parameter supported by most CryptContext
    methods.

    These options are conditional because they only take effect if
    the :samp:`{category}` prefix of the option matches the value of the ``category``
    parameter of the CryptContext method being invoked. In that case,
    they override any options specified without a category
    prefix (e.g. `admin__sha256_crypt__min_rounds` would override
    `sha256_crypt__min_rounds`).
    The category prefix and the value passed into the ``category`` parameter
    can be any string the application wishes to use, the only constraint
    is that ``None`` indicates the default category.

*Motivation:*
Policy limits such as default rounds values and deprecated schemes
generally have to be set globally. However, it's frequently desirable
to specify stronger options for certain accounts (such as admin accounts),
choosing to sacrifice longer hashing time for a more secure password.
The user categories system allows for this.
For example, a CryptContext could be set up as follows::

    >>> # A context object can be set up as follows:
    >>> from passlib.context import CryptContext
    >>> myctx = CryptContext(schemes=["sha256_crypt"],
    ...                      sha256_crypt__default_rounds=77000,
    ...                      staff__sha256_crypt__default_rounds=88000)

    >>> # In this case, calling hash() with ``category=None`` would result
    >>> # in a hash that used 77000 sha256-crypt rounds:
    >>> myctx.hash("password", category=None)
    '$5$rounds=77000$sj3XI0AbKlEydAKt$BhFvyh4.IoxaUeNlW6rvQ.O0w8BtgLQMYorkCOMzf84'
               ^^^^^

    >>> # But if the application passed in ``category="staff"`` when an administrative
    >>> # account set their password, 88000 rounds would be used:
    >>> myctx.hash("password", category="staff")
    '$5$rounds=88000$w7XIdKfTI9.YLwmA$MIzGvs6NU1QOQuuDHhICLmDsdW/t94Bbdfxdh/6NJl7'
               ^^^^^

.. rst-class:: html-toggle expanded

Primary Methods
---------------
The main interface to the CryptContext object deliberately mirrors
the :ref:`PasswordHash <password-hash-api>` interface, since its central
purpose is to act as a container for multiple password hashes.
Most applications will only need to make use two methods in a CryptContext
instance:

.. automethod:: CryptContext.hash
.. automethod:: CryptContext.encrypt
.. automethod:: CryptContext.verify
.. automethod:: CryptContext.identify
.. automethod:: CryptContext.dummy_verify

.. rst-class:: html-toggle

"crypt"-style methods
.....................
Additionally, the main interface offers wrappers for the two Unix "crypt"
style methods provided by all the :class:`~passlib.ifc.PasswordHash` objects:

.. automethod:: CryptContext.genhash
.. automethod:: CryptContext.genconfig

.. rst-class:: html-toggle expanded

Hash Migration
--------------
Applications which want to detect and regenerate deprecated
hashes will want to use one of the following methods:

.. automethod:: CryptContext.verify_and_update
.. automethod:: CryptContext.needs_update
.. automethod:: CryptContext.hash_needs_update

.. rst-class:: html-toggle expanded

.. _context-disabled-hashes:

Disabled Hash Managment
-----------------------
.. versionadded:: 1.7

It's frequently useful to disable a user's ability to login by
replacing their password hash with a standin that's guaranteed
to never verify, against *any* password.   CryptContext offers
some convenience methods for this through the following API.

.. automethod:: CryptContext.disable
.. automethod:: CryptContext.enable
.. automethod:: CryptContext.is_enabled

Alternate Constructors
----------------------
In addition to the main class constructor, which accepts a configuration
as a set of keywords, there are the following alternate constructors:

.. automethod:: CryptContext.from_string
.. automethod:: CryptContext.from_path
.. automethod:: CryptContext.copy

.. rst-class:: html-toggle expanded

Changing the Configuration
--------------------------
:class:`CryptContext` objects can have their configuration replaced or updated
on the fly, and from a variety of sources (keywords, strings, files).
This is done through three methods:

.. automethod:: CryptContext.update(\*\*kwds)
.. automethod:: CryptContext.load
.. automethod:: CryptContext.load_path

.. rst-class:: html-toggle expanded

Examining the Configuration
---------------------------
The CryptContext object also supports basic inspection of its
current configuration:

.. automethod:: CryptContext.schemes
.. automethod:: CryptContext.default_scheme
.. automethod:: CryptContext.handler
.. autoattribute:: CryptContext.context_kwds

.. rst-class:: html-toggle expanded

Saving the Configuration
------------------------
More detailed inspection can be done by exporting the configuration
using one of the serialization methods:

.. automethod:: CryptContext.to_dict
.. automethod:: CryptContext.to_string

Configuration Errors
--------------------
The following errors may be raised when creating a :class:`!CryptContext` instance
via any of its constructors, or when updating the configuration of an existing
instance:

:raises ValueError:

    * If a configuration option contains an invalid value
      (e.g. ``all__vary_rounds=-1``).

    * If the configuration contains valid but incompatible options
      (e.g. listing a scheme as both :ref:`default <context-default-option>`
      and :ref:`deprecated <context-deprecated-option>`).

:raises KeyError:

    * If the configuration contains an unknown or forbidden option
      (e.g. :samp:`{scheme}__salt`).

    * If the :ref:`schemes <context-schemes-option>`,
      :ref:`default <context-default-option>`, or
      :ref:`deprecated <context-deprecated-option>` options reference an unknown
      hash scheme (e.g. ``schemes=['xxx']``)

:raises TypeError:

    * If a configuration value has the wrong type (e.g. ``schemes=123``).

    Note that this error shouldn't occur when loading configurations
    from a file/string (e.g. using :meth:`CryptContext.from_string`).

Additionally, a :exc:`~passlib.exc.PasslibConfigWarning` may be issued
if any invalid-but-correctable values are encountered
(e.g. if :samp:`sha256_crypt__min_rounds` is set to less than
:class:`~passlib.hash.sha256_crypt` 's minimum of 1000).

.. versionchanged:: 1.6
    Previous releases used Python's builtin :exc:`UserWarning` instead
    of the more specific :exc:`!passlib.exc.PasslibConfigWarning`.

Other Helpers
=============
.. autoclass:: LazyCryptContext([schemes=None,] \*\*kwds [, onload=None])

.. rst-class:: html-toggle

The CryptPolicy Class (deprecated)
==================================
.. autoclass:: CryptPolicy