1"""passlib.handlers.postgres_md5 - MD5-based algorithm used by Postgres for pg_shadow table"""
2#=============================================================================
3# imports
4#=============================================================================
5# core
6from hashlib import md5
7import logging; log = logging.getLogger(__name__)
8# site
9# pkg
10from passlib.utils import to_bytes
11from passlib.utils.compat import str_to_uascii, unicode, u
12import passlib.utils.handlers as uh
13# local
14__all__ = [
15    "postgres_md5",
16]
17
18#=============================================================================
19# handler
20#=============================================================================
21class postgres_md5(uh.HasUserContext, uh.StaticHandler):
22    """This class implements the Postgres MD5 Password hash, and follows the :ref:`password-hash-api`.
23
24    It does a single round of hashing, and relies on the username as the salt.
25
26    The :meth:`~passlib.ifc.PasswordHash.hash`, :meth:`~passlib.ifc.PasswordHash.genhash`, and :meth:`~passlib.ifc.PasswordHash.verify` methods all require the
27    following additional contextual keywords:
28
29    :type user: str
30    :param user: name of postgres user account this password is associated with.
31    """
32    #===================================================================
33    # algorithm information
34    #===================================================================
35    name = "postgres_md5"
36    _hash_prefix = u("md5")
37    checksum_chars = uh.HEX_CHARS
38    checksum_size = 32
39
40    #===================================================================
41    # primary interface
42    #===================================================================
43    def _calc_checksum(self, secret):
44        if isinstance(secret, unicode):
45            secret = secret.encode("utf-8")
46        user = to_bytes(self.user, "utf-8", param="user")
47        return str_to_uascii(md5(secret + user).hexdigest())
48
49    #===================================================================
50    # eoc
51    #===================================================================
52
53#=============================================================================
54# eof
55#=============================================================================
56