
    XR_N                     d   d Z ddlmZ ddlmZ ddlmZmZmZ ddl	Z	 e	j
        e          ZddlmZ ddlmZmZmZmZ ddlmZmZmZ dd	lmZ dd
lmZmZmZmZ ddlm Z  ddl!m"c m#Z$ g dZ%da&d Z'dZ( G d de$j)        e$j*                  Z+ G d de$j,        e+          Z- G d de+          Z. G d de+          Z/ e$j0        de ed           ed          d          Z1de1_2        e1xj3        dz  c_3         G d de          Z4 G d d e-          Z5 G d! d"e5          Z6 e$j0        d# ej7        d$%           ed&           ed'          d()          Z8d&e8_2        e8xj3        dz  c_3         G d* d+e$j9        e$j)        e$j*                  Z: G d, d-e$j;        j<        e$j=                  Z>dS ).z5passlib.handlers.django- Django password hash support    )	b64encode)hexlify)md5sha1sha256N)_wrapped_bcrypt)argon2bcryptpbkdf2_sha1pbkdf2_sha256)
to_unicoderng
getrandstr)BASE64_CHARS)str_to_uasciiuascii_to_strunicodeu)pbkdf2_hmac)django_salted_sha1django_salted_md5django_bcryptdjango_pbkdf2_sha1django_pbkdf2_sha256django_argon2django_des_cryptdjango_disabledc                  *    t           ddlm a  t           S )Nr   )	des_crypt)r   passlib.hash     9/usr/lib/python3/dist-packages/passlib/handlers/django.py_import_des_cryptr$   &   s     ******r"   >abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789c                   L    e Zd ZdZdZdZdZeZe	j
        Zed             Zd ZdS )DjangoSaltedHashz2base class providing common code for django hashes)salt	salt_size   Nc                 Z    t          j        || j        |           \  }} | ||          S )Nhandlerr(   checksum)uh	parse_mc2identclshashr(   chks       r#   from_stringzDjangoSaltedHash.from_stringB   s3    Lsy#>>>	css++++r"   c                 L    t          j        | j        | j        | j                  S N)r0   
render_mc2r2   r(   r/   selfs    r#   	to_stringzDjangoSaltedHash.to_stringG   s    }TZDMBBBr"   )__name__
__module____qualname____doc__setting_kwdsdefault_salt_sizemax_salt_size
SALT_CHARS
salt_charsr0   LOWER_HEX_CHARSchecksum_charsclassmethodr7   r=   r!   r"   r#   r'   r'   2   sh        << )L MJ'N, , [,C C C C Cr"   r'   c                   F    e Zd ZdZej        dz   ZdZed             Zd Z	dS )DjangoVariableHashzEbase class providing common code for django hashes w/ variable rounds)rounds   c                 ^    t          j        || j        |           \  }}} | |||          S )Nr,   )rL   r(   r/   )r0   	parse_mc3r2   )r4   r5   rL   r(   r6   s        r#   r7   zDjangoVariableHash.from_stringQ   s8    Lsy#FFFcs&tc::::r"   c                 X    t          j        | j        | j        | j        | j                  S r9   )r0   
render_mc3r2   rL   r(   r/   r;   s    r#   r=   zDjangoVariableHash.to_stringV   s     }TZdiOOOr"   N)
r>   r?   r@   rA   r'   rB   
min_roundsrI   r7   r=   r!   r"   r#   rK   rK   K   sY        OO#0;>LJ; ; [;P P P P Pr"   rK   c                   :    e Zd ZdZd ZdZ ed          ZdZd Z	dS )r   a  This class implements Django's Salted SHA1 hash, and follows the :ref:`password-hash-api`.

    It supports a variable-length salt, and uses a single round of SHA1.

    The :meth:`~passlib.ifc.PasswordHash.hash` and :meth:`~passlib.ifc.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.

    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.
    r   zsha1$(   c                     t          |t                    r|                    d          }t          t	          | j                            d          |z                                                       S Nutf-8ascii)
isinstancer   encoder   r   r(   	hexdigestr<   secrets     r#   _calc_checksumz!django_salted_sha1._calc_checksumy   s\    fg&& 	,]]7++FT$)"2"27";";f"DEEOOQQRRRr"   N
r>   r?   r@   rA   namedjango_namer   r2   checksum_sizer^   r!   r"   r#   r   r   Y   sP         4  DKAgJJEMS S S S Sr"   r   c                   :    e Zd ZdZd ZdZ ed          ZdZd Z	dS )r   a  This class implements Django's Salted MD5 hash, and follows the :ref:`password-hash-api`.

    It supports a variable-length salt, and uses a single round of MD5.

    The :meth:`~passlib.ifc.PasswordHash.hash` and :meth:`~passlib.ifc.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.

    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.
    r   zmd5$    c                     t          |t                    r|                    d          }t          t	          | j                            d          |z                                                       S rV   )rY   r   rZ   r   r   r(   r[   r\   s     r#   r^   z django_salted_md5._calc_checksum   s\    fg&& 	,]]7++FS!1!1'!:!:V!CDDNNPPQQQr"   Nr_   r!   r"   r#   r   r   ~   sP         6 DKAfIIEMR R R R Rr"   r   r   zbcrypt$a  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
    )prefixr2   docr
   )ra   c                   ~     e Zd ZdZd ZdZeZ ed          Z	e
d             Ze
 fd            Z fdZ fdZ xZS )django_bcrypt_sha256a  This class implements Django 1.6's Bcrypt+SHA256 hash, and follows the :ref:`password-hash-api`.

    It supports a variable-length salt, and a variable number of rounds.

    While the algorithm and format is somewhat different,
    the api and options for this hash are identical to :class:`!bcrypt` itself,
    see :doc:`bcrypt </lib/passlib.hash.bcrypt>` for more details.

    .. versionadded:: 1.6.2
    bcrypt_sha256zbcrypt_sha256$c                 f    t          j        |          }|sdS |                    | j                  S NF)r0   to_unicode_for_identify
startswithdjango_prefixr4   r5   s     r#   identifyzdjango_bcrypt_sha256.identify   s4    )$// 	5s0111r"   c                    t          |dd          }|                    | j                  st          j                            |           |t          | j                  d          }|                    d          st          j                            |           t          t          |           
                    |          S )NrX   r5   z$2)r   rn   ro   r0   excInvalidHashErrorlenMalformedHashErrorsuperri   r7   )r4   r5   bhash	__class__s      r#   r7   z django_bcrypt_sha256.from_string   s    $00s011 	/&))#...S*++,,-%% 	1&++C000)3//;;EBBBr"   c                     t          t          |                                           }t          | j                  |z   S r9   )rw   ri   r=   r   ro   )r<   rx   ry   s     r#   r=   zdjango_bcrypt_sha256.to_string   s5    *D11;;==T/00588r"   c                    t          |t                    r|                    d          }t          |                     |                                                    }t          t          |                               |          S )NrW   )	rY   r   rZ   r   _digestdigestrw   ri   r^   )r<   r]   ry   s     r#   r^   z#django_bcrypt_sha256._calc_checksum   sj    fg&& 	,]]7++Ff--446677)400??GGGr"   )r>   r?   r@   rA   r`   ra   r   r|   r   ro   rI   rq   r7   r=   r^   __classcell__)ry   s   @r#   ri   ri      s        	 	 "D!KG A&''M2 2 [2 C C C C [C9 9 9 9 9H H H H H H H H Hr"   ri   c                   b    e Zd ZdZd ZdZ ed          ZdZdZ	e
j        ZdZej        ZdZd Zd	S )
r   a  This class implements Django's PBKDF2-HMAC-SHA256 hash, and follows the :ref:`password-hash-api`.

    It supports a variable-length salt, and a variable number of rounds.

    The :meth:`~passlib.ifc.PasswordHash.using` method accepts 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 29000, but must be within ``range(1,1<<32)``.

    :type relaxed: bool
    :param relaxed:
        By default, providing an invalid value for one of the other
        keywords will result in a :exc:`ValueError`. If ``relaxed=True``,
        and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`
        will be issued instead. Correctable errors include ``rounds``
        that are too small or too large, and ``salt`` strings that are too long.

    This should be compatible with the hashes generated by
    Django 1.4's :class:`!PBKDF2PasswordHasher` class.

    .. versionadded:: 1.6
    r   zpbkdf2_sha256$rM   l    ,   r   c                     t          | j        || j        | j                  }t	          |                                                              d          S )NrX   )r   r|   r(   rL   r   rstripdecode)r<   r]   r5   s      r#   r^   z#django_pbkdf2_sha256._calc_checksum#  sA    4<DKHH%%''..w777r"   N)r>   r?   r@   rA   r`   ra   r   r2   min_salt_size
max_roundsr0   PADDED_BASE64_CHARSrH   rb   r   default_roundsr|   r^   r!   r"   r#   r   r      sn        " "F "D!KAEMJ+NM"1NG8 8 8 8 8r"   r   c                   F    e Zd ZdZd ZdZ ed          ZdZe	j
        Z
dZdS )r   a  This class implements Django's PBKDF2-HMAC-SHA1 hash, and follows the :ref:`password-hash-api`.

    It supports a variable-length salt, and a variable number of rounds.

    The :meth:`~passlib.ifc.PasswordHash.using` method accepts 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 131000, but must be within ``range(1,1<<32)``.

    :type relaxed: bool
    :param relaxed:
        By default, providing an invalid value for one of the other
        keywords will result in a :exc:`ValueError`. If ``relaxed=True``,
        and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`
        will be issued instead. Correctable errors include ``rounds``
        that are too small or too large, and ``salt`` strings that are too long.

    This should be compatible with the hashes generated by
    Django 1.4's :class:`!PBKDF2SHA1PasswordHasher` class.

    .. versionadded:: 1.6
    r   zpbkdf2_sha1$   r   N)r>   r?   r@   rA   r`   ra   r   r2   rb   r   r   r|   r!   r"   r#   r   r   (  sF        " "F  DKAnEM /NGGGr"   r   r   I)typer	   zargon2$argon2i$a  This class implements Django 1.10's Argon2 wrapper, and follows the :ref:`password-hash-api`.

    This is identical to :class:`!argon2` itself, but with
    the Django-specific prefix ``"argon2$"`` prepended.

    See :doc:`argon2 </lib/passlib.hash.argon2>` for more details,
    the usage and behavior is identical.

    This should be compatible with the hashes generated by
    Django 1.10's :class:`!Argon2PasswordHasher` class.

    .. versionadded:: 1.7
    )r`   wrappedrf   r2   rg   c                   |    e Zd ZdZd ZdZdZ ed          Ze	j
        xZZdZdxZZdZdZed	             Zd
 Zd ZdS )r   a  This class implements Django's :class:`des_crypt` wrapper, and follows the :ref:`password-hash-api`.

    It supports a fixed-length salt.

    The :meth:`~passlib.ifc.PasswordHash.hash` and :meth:`~passlib.ifc.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]``.

    :param bool truncate_error:
        By default, django_des_crypt will silently truncate passwords larger than 8 bytes.
        Setting ``truncate_error=True`` will cause :meth:`~passlib.ifc.PasswordHash.hash`
        to raise a :exc:`~passlib.exc.PasswordTruncateError` instead.

        .. versionadded:: 1.7

    This should be compatible with the hashes generated by
    Django 1.4's :class:`!CryptPasswordHasher` class.
    Note that Django only supports this hash on Unix systems
    (though :class:`!django_des_crypt` is available cross-platform
    under Passlib).

    .. versionchanged:: 1.6
        This class will now accept hashes with empty salt strings,
        since Django 1.4 generates them this way.
    crypt)r(   r)   truncate_errorzcrypt$         Tc                     t          j        || j        |           \  }}|rM|s|d d         }n6|d d         |d d         k    r t           j                            | d          |dd          } | ||          S )Nr,   r   z0first two digits of salt and checksum must matchr.   )r0   r1   r2   rs   rv   r3   s       r#   r7   zdjango_des_crypt.from_string  s    Lsy#>>>	c 	 	H 2A2wbqbS!W$$ f//FH H H abb'Css++++r"   c                     | j         }|d d         | j        z   }| j        rt          j        | j        ||          S t          j        | j        d|          S )Nr    )r(   r/   use_duplicate_saltr0   r:   r2   )r<   r(   r6   s      r#   r=   zdjango_des_crypt.to_string  sV    y2A2h&" 	6=T3777 =R555r"   c                     t           t                       | j        r|                     |           t          | j        d d                                       |          S )Nr   )r(   )r   r$   use_defaults_check_truncate_policyr(   r^   r\   s     r#   r^   zdjango_des_crypt._calc_checksum  s^      	0''///dim,,,;;FCCCr"   N)r>   r?   r@   rA   r`   ra   rB   r   r2   r0   HASH64_CHARSrH   rF   rb   r   rC   truncate_sizer   rI   r7   r=   r^   r!   r"   r#   r   r   t  s         : DK:LAhKKE"$/1NZM())M%M , , [,$6 6 6	D 	D 	D 	D 	Dr"   r   c                   b    e Zd ZdZd Z ed          ZdZed             Z	d Z
ed             ZdS )r   aF  This class provides disabled password behavior for Django, and follows the :ref:`password-hash-api`.

    This class does not implement a hash, but instead
    claims the special hash string ``"!"`` which Django uses
    to indicate an account's password has been disabled.

    * newly encrypted passwords will hash to ``"!"``.
    * it rejects all passwords.

    .. note::

        Django 1.6 prepends a randomly generated 40-char alphanumeric string
        to each unusuable password. This class recognizes such strings,
        but for backwards compatibility, still returns ``"!"``.

        See `<https://code.djangoproject.com/ticket/20079>`_ for why
        Django appends an alphanumeric string.

    .. versionchanged:: 1.6.2 added Django 1.6 support

    .. versionchanged:: 1.7 started appending an alphanumeric string.
    !rT   c                 ^    t          j        |          }|                    | j                  S r9   )r0   rm   rn   _hash_prefixrp   s     r#   rq   zdjango_disabled.identify  s'    )$//s/000r"   c                 R    t          t          t          d d         | j                  S )N)r   r   r   suffix_lengthr\   s     r#   r^   zdjango_disabled._calc_checksum  s     #|CRC0$2DEEEr"   c                     t          j        |           |                     |          st           j                            |           dS rl   )r0   validate_secretrq   rs   rt   )r4   r]   r5   s      r#   verifyzdjango_disabled.verify  sB    
6"""||D!! 	/&))#...ur"   N)r>   r?   r@   rA   r`   r   r   r   rI   rq   r^   r   r!   r"   r#   r   r     s         , D1S66LM 1 1 [1F F F   [  r"   r   )?rA   base64r   binasciir   hashlibr   r   r   logging	getLoggerr>   logpasslib.handlers.bcryptr   r    r	   r
   r   r   passlib.utilsr   r   r   passlib.utils.binaryr   passlib.utils.compatr   r   r   r   passlib.crypto.digestr   passlib.utils.handlersutilshandlersr0   __all__r   r$   rE   HasSaltGenericHandlerr'   	HasRoundsrK   r   r   PrefixWrapperr   ra   _using_clone_attrsri   r   r   usingr   TruncateMixinr   ifcDisabledHashStaticHandlerr   r!   r"   r#   <module>r      s   ; ;
             % % % % % % % % % % 'g'11 4 3 3 3 3 3 C C C C C C C C C C C C 5 5 5 5 5 5 5 5 5 5 - - - - - - I I I I I I I I I I I I - - - - - - # # # # # # # # #	 	 	  	   N

C C C C Crz2#4 C C C2P P P P P'7 P P P#S #S #S #S #S) #S #S #SJ$R $R $R $R $R( $R $R $RT ! &1Y<<qq||			 	 	" %      $4 4    /H /H /H /H /H? /H /H /Hj18 18 18 18 18- 18 18 18f) ) ) ) )- ) ) )d ! 	FLc"""1X;;
!

		 	 	( %      $4 4    
\D \D \D \D \Dr'R5F \D \D \D|* * * * *bf)2+; * * * * *r"   