passlib.hash - Password Hashing Schemes

Overview

The 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 Password Hash Interface. The following pages describe the common interface, and then describe each hash in detail (including it’s format, underlying algorithm, and known security issues).

See also

Quickstart Guide – 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 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 CryptContext object instead; and reference the hashes by name only. For example, the following code creates a CryptContext object which recognizes both the md5_crypt and 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:

Unix & “Modular Crypt” Hashes

Aside from the “archaic” schemes below, most modern Unix flavors use password hashes which follow the modular crypt format, allowing them to be easily distinguished when used within the same file. The basic format $scheme$hash has also been adopted for use by other applications and password hash schemes.

Archaic Unix Schemes

All of the following hashes are/were used by various Unix flavors to store user passwords; most are based on the DES block cipher, and predate the arrival of the modular crypt format. They should all be considered insecure at best, but may be useful when reading legacy password entries:

Standard Unix Schemes

All these schemes are currently used by various Unix flavors to store user passwords. They all follow the modular crypt format.

Other Modular Crypt Schemes

While most of these schemes are not (commonly) used by any Unix flavor to store user passwords, they can be used compatibly along side other modular crypt format hashes.

Special note should be made of the fallback helper, which is not an actual hash scheme, but provides “disabled account” behavior found in many Linux & BSD password files:

LDAP / RFC2307 Hashes

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 [1], the basic format {SCHEME}HASH has seen widespread adoption in a number of programs.

[1]OpenLDAP homepage - http://www.openldap.org/.

Standard LDAP Schemes

The following schemes are explicitly defined by RFC 2307, and are supported by OpenLDAP.

Non-Standard LDAP Schemes

None of the following schemes are actually used by LDAP, but follow the LDAP format:

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.