U
    hN                     @   s  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	
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"  m#Z$ ddddddddgZ%da&dd Z'dZ(G dd de$j)e$j*Z+G dd de$j,e+Z-G dd de+Z.G dd de+Z/e$j0deededddZ1d e1_2e1 j3d!7  _3G d"d# d#eZ4G d$d de-Z5G d%d de5Z6e$j0dej7d&d'ed(ed)d*d+Z8d(e8_2e8 j3d!7  _3G d,d de$j9e$j)e$j*Z:G d-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                   C   s   t d krddlm a  t S )Nr   )	des_crypt)r   passlib.hash r   r   =./venv/lib/python3.8/site-packages/passlib/handlers/django.py_import_des_crypt&   s    r!   Z>abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789c                   @   s:   e Zd ZdZdZdZdZeZe	j
Zedd Zdd ZdS )	DjangoSaltedHashz2base class providing common code for django hashes)salt	salt_size   Nc                 C   s"   t j|| j| d\}}| ||dS )NZhandlerr#   checksum)uh	parse_mc2identclshashr#   chkr   r   r    from_stringB   s    zDjangoSaltedHash.from_stringc                 C   s   t | j| j| jS N)r)   
render_mc2r+   r#   r(   selfr   r   r    	to_stringG   s    zDjangoSaltedHash.to_string)__name__
__module____qualname____doc__setting_kwdsdefault_salt_sizeZmax_salt_size
SALT_CHARS
salt_charsr)   ZLOWER_HEX_CHARSchecksum_charsclassmethodr0   r5   r   r   r   r    r"   2   s   
r"   c                   @   s2   e Zd ZdZejd ZdZedd Zdd Z	dS )	DjangoVariableHashzEbase class providing common code for django hashes w/ variable rounds)rounds   c                 C   s&   t j|| j| d\}}}| |||dS )Nr&   )rA   r#   r(   )r)   Z	parse_mc3r+   )r-   r.   rA   r#   r/   r   r   r    r0   Q   s    zDjangoVariableHash.from_stringc                 C   s   t | j| j| j| jS r1   )r)   Z
render_mc3r+   rA   r#   r(   r3   r   r   r    r5   V   s    zDjangoVariableHash.to_stringN)
r6   r7   r8   r9   r"   r:   Z
min_roundsr?   r0   r5   r   r   r   r    r@   K   s   

r@   c                   @   s,   e Zd ZdZd ZdZedZdZd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                 C   s0   t |tr|d}tt| jd|  S Nutf-8ascii)
isinstancer   encoder   r   r#   	hexdigestr4   secretr   r   r    _calc_checksumy   s    

z!django_salted_sha1._calc_checksumN
r6   r7   r8   r9   namedjango_namer   r+   checksum_sizerL   r   r   r   r    r   Y   s   c                   @   s,   e Zd ZdZd ZdZedZdZd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                 C   s0   t |tr|d}tt| jd|  S rD   )rG   r   rH   r   r   r#   rI   rJ   r   r   r    rL      s    

z django_salted_md5._calc_checksumNrM   r   r   r   r    r   ~   s   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
    )prefixr+   docr	   )rO   c                       s\   e Zd ZdZd ZdZeZedZ	e
dd Ze
 fddZ fdd	Z fd
dZ  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
    Zbcrypt_sha256zbcrypt_sha256$c                 C   s   t |}|sdS || jS NF)r)   to_unicode_for_identify
startswithdjango_prefixr-   r.   r   r   r    identify   s    
zdjango_bcrypt_sha256.identifyc                    s\   t |dd}|| js$tj| |t| jd  }|dsLtj| tt	| 
|S )NrF   r.   z$2)r   rW   rX   r)   excInvalidHashErrorlenMalformedHashErrorsuperrT   r0   )r-   r.   bhash	__class__r   r    r0      s    
z django_bcrypt_sha256.from_stringc                    s   t t|  }t| j| S r1   )r_   rT   r5   r   rX   )r4   r`   ra   r   r    r5      s    zdjango_bcrypt_sha256.to_stringc                    s6   t |tr|d}t| | }tt| |S )NrE   )	rG   r   rH   r   _digestZdigestr_   rT   rL   rJ   ra   r   r    rL      s    

z#django_bcrypt_sha256._calc_checksum)r6   r7   r8   r9   rN   rO   r   rc   r   rX   r?   rZ   r0   r5   rL   __classcell__r   r   ra   r    rT      s   

	rT   c                   @   sD   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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$rB   l    ,   r   c                 C   s&   t | j|| j| j}t| dS )NrF   )r   rc   r#   rA   r   rstripdecode)r4   rK   r.   r   r   r    rL   #  s    z#django_pbkdf2_sha256._calc_checksumN)r6   r7   r8   r9   rN   rO   r   r+   min_salt_sizeZ
max_roundsr)   ZPADDED_BASE64_CHARSr>   rP   r   default_roundsrc   rL   r   r   r   r    r      s   #c                   @   s.   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)r6   r7   r8   r9   rN   rO   r   r+   rP   r
   ri   rc   r   r   r   r    r   (  s   #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
    )rN   wrappedrR   r+   rS   c                   @   s^   e Zd ZdZd ZdZdZedZe	j
 ZZdZd ZZdZdZed	d
 Zdd Zd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.
    Zcrypt)r#   r$   Ztruncate_errorzcrypt$         Tc                 C   sj   t j|| j| d\}}|r^|s,|d d }n&|d d |d d krRt j| d|dd  }| ||dS )Nr&   ro   z0first two digits of salt and checksum must matchr'   )r)   r*   r+   r[   r^   r,   r   r   r    r0     s    zdjango_des_crypt.from_stringc                 C   sB   | j }|d d | j }| jr.t| j||S t| jd|S d S )Nro    )r#   r(   use_duplicate_saltr)   r2   r+   )r4   r#   r/   r   r   r    r5     s
    zdjango_des_crypt.to_stringc                 C   s8   t d krt  | jr| | t | jd d d|S )Nro   )r#   )r   r!   Zuse_defaultsZ_check_truncate_policyr#   rL   rJ   r   r   r    rL     s
    
zdjango_des_crypt._calc_checksumN)r6   r7   r8   r9   rN   rO   r:   r   r+   r)   ZHASH64_CHARSr>   r=   rP   rh   r;   Ztruncate_sizerr   r?   r0   r5   rL   r   r   r   r    r   t  s   


c                   @   s@   e Zd ZdZd ZedZdZedd Z	dd Z
ed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.
    !rC   c                 C   s   t |}|| jS r1   )r)   rV   rW   _hash_prefixrY   r   r   r    rZ     s    
zdjango_disabled.identifyc                 C   s   t ttd d | jS )N)r   r   r   suffix_lengthrJ   r   r   r    rL     s    zdjango_disabled._calc_checksumc                 C   s$   t | | |s t j| dS rU   )r)   Zvalidate_secretrZ   r[   r\   )r-   rK   r.   r   r   r    verify  s    

zdjango_disabled.verifyN)r6   r7   r8   r9   rN   r   rt   rv   r?   rZ   rL   rw   r   r   r   r    r     s   
)?r9   base64r   Zbinasciir   Zhashlibr   r   r   ZloggingZ	getLoggerr6   logZpasslib.handlers.bcryptr   r   r   r	   r
   r   Zpasslib.utilsr   r   r   Zpasslib.utils.binaryr   Zpasslib.utils.compatr   r   r   r   Zpasslib.crypto.digestr   Zpasslib.utils.handlersZutilsZhandlersr)   __all__r   r!   r<   ZHasSaltZGenericHandlerr"   Z	HasRoundsr@   r   r   ZPrefixWrapperr   rO   Z_using_clone_attrsrT   r   r   Zusingr   ZTruncateMixinr   ZifcZDisabledHashZStaticHandlerr   r   r   r   r    <module>   sb    
%* 532
^