
    gN                        S r SSKJr  SSKJr  SSKJrJrJr  SSK	r	\	R                  " \5      rSSKJr  SSKJrJrJrJr  SSKJrJrJr  SS	KJr  SS
KJrJrJrJr  SSKJ r   SSK!J"s  J#r$  / SQr%Sq&S r'Sr( " S S\$RR                  \$RT                  5      r+ " S S\$RX                  \+5      r- " S S\+5      r. " S S\+5      r/\$R`                  " S\\" S5      \" S5      SS9r1S\1l2        \1=Rf                  S-  sl3         " S S\5      r4 " S S \-5      r5 " S! S"\55      r6\$R`                  " S#\Rn                  " S$S%9\" S&5      \" S'5      S(S)9r8S&\8l2        \8=Rf                  S-  sl3         " S* S+\$Rr                  \$RR                  \$RT                  5      r: " S, S-\$Rv                  Rx                  \$Rz                  5      r>g).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SKJ q   [         $ )Nr   )	des_crypt)r   passlib.hash     P/home/matz/Project1/venv/lib/python3.13/site-packages/passlib/handlers/django.py_import_des_cryptr$   &   s    *r"   >abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789c                   V    \ rS rSrSrSrSrSr\r	\
R                  r\S 5       rS rSrg)	DjangoSaltedHash2   z2base class providing common code for django hashes)salt	salt_size   Nc                 P    [         R                  " XR                  U S9u  p#U " X#S9$ )Nhandlerr)   checksum)uh	parse_mc2identclshashr)   chks       r#   from_stringDjangoSaltedHash.from_stringB   s#    LLyy#>	++r"   c                 n    [         R                  " U R                  U R                  U R                  5      $ N)r1   
render_mc2r3   r)   r0   selfs    r#   	to_stringDjangoSaltedHash.to_stringG   s!    }}TZZDMMBBr"   r!   )__name__
__module____qualname____firstlineno____doc__setting_kwdsdefault_salt_sizemax_salt_size
SALT_CHARS
salt_charsr1   LOWER_HEX_CHARSchecksum_charsclassmethodr8   r?   __static_attributes__r!   r"   r#   r'   r'   2   sA    < )L MJ''N, ,Cr"   r'   c                   P    \ rS rSrSr\R                  S-   rSr\S 5       r	S r
Srg)	DjangoVariableHashK   zEbase class providing common code for django hashes w/ variable rounds)rounds   c                 T    [         R                  " XR                  U S9u  p#nU " X#US9$ )Nr-   )rR   r)   r0   )r1   	parse_mc3r3   )r5   r6   rR   r)   r7   s        r#   r8   DjangoVariableHash.from_stringQ   s(    LLyy#Fc&c::r"   c                     [         R                  " U R                  U R                  U R                  U R
                  5      $ r;   )r1   
render_mc3r3   rR   r)   r0   r=   s    r#   r?   DjangoVariableHash.to_stringV   s'    }}TZZdiiOOr"   r!   N)rA   rB   rC   rD   rE   r'   rF   
min_roundsrM   r8   r?   rN   r!   r"   r#   rP   rP   K   s2    O#00;>LJ; ;Pr"   rP   c                   :    \ rS rSrSrS rSr\" S5      rSr	S r
Srg)	r   Y   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                     [        U[        5      (       a  UR                  S5      n[        [	        U R
                  R                  S5      U-   5      R                  5       5      $ Nutf-8ascii)
isinstancer   encoder   r   r)   	hexdigestr>   secrets     r#   _calc_checksum!django_salted_sha1._calc_checksumy   sJ    fg&&]]7+FT$))"2"27";f"DEOOQRRr"   r!   NrA   rB   rC   rD   rE   namedjango_namer   r3   checksum_sizerg   rN   r!   r"   r#   r   r   Y   s'    4  DKgJEMSr"   r   c                   :    \ rS rSrSrS rSr\" S5      rSr	S r
Srg)	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                     [        U[        5      (       a  UR                  S5      n[        [	        U R
                  R                  S5      U-   5      R                  5       5      $ r_   )rb   r   rc   r   r   r)   rd   re   s     r#   rg    django_salted_md5._calc_checksum   sJ    fg&&]]7+FS!1!1'!:V!CDNNPQQr"   r!   Nri   r!   r"   r#   r   r   ~   s'    6 DKfIEM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
    )prefixr3   docr
   )rk   c                   z   ^  \ rS rSrSrS rSr\r\	" S5      r
\S 5       r\U 4S j5       rU 4S jrU 4S jrS	rU =r$ )
django_bcrypt_sha256   a  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                 t    [         R                  " U5      nU(       d  gUR                  U R                  5      $ NF)r1   to_unicode_for_identify
startswithdjango_prefixr5   r6   s     r#   identifydjango_bcrypt_sha256.identify   s-    ))$/s0011r"   c                 \  > [        USS5      nUR                  U R                  5      (       d  [        R                  R                  U 5      eU[        U R                  5      S  nUR                  S5      (       d  [        R                  R                  U 5      e[        [        U ]+  U5      $ )Nra   r6   z$2)r   r{   r|   r1   excInvalidHashErrorlenMalformedHashErrorsuperru   r8   )r5   r6   bhash	__class__s      r#   r8    django_bcrypt_sha256.from_string   s    $0s0011&&))#..S**+,-%%&&++C00)3;EBBr"   c                 X   > [         [        U ]  5       n[        U R                  5      U-   $ r;   )r   ru   r?   r   r|   )r>   r   r   s     r#   r?   django_bcrypt_sha256.to_string   s)    *D;=T//0588r"   c                    > [        U[        5      (       a  UR                  S5      n[        U R	                  U5      R                  5       5      n[        [        U ]#  U5      $ )Nr`   )	rb   r   rc   r   _digestdigestr   ru   rg   )r>   rf   r   s     r#   rg   #django_bcrypt_sha256._calc_checksum   sM    fg&&]]7+Ff-4467)4?GGr"   r!   )rA   rB   rC   rD   rE   rj   rk   r   r   r   r|   rM   r~   r8   r?   rg   rN   __classcell__)r   s   @r#   ru   ru      s_    	 "D!KG &'M2 2 C C9H Hr"   ru   c                   v    \ rS rSrSrS rSr\" S5      rSr	Sr
\R                  rSr\R                   rSrS	 rS
rg)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$rS   l    ,   r   c                     [        U R                  XR                  U R                  5      n[	        U5      R                  5       R                  S5      $ )Nra   )r   r   r)   rR   r   rstripdecode)r>   rf   r6   s      r#   rg   #django_pbkdf2_sha256._calc_checksum#  s:    4<<DKKH%%'..w77r"   r!   N)rA   rB   rC   rD   rE   rj   rk   r   r3   min_salt_size
max_roundsr1   PADDED_BASE64_CHARSrL   rl   r   default_roundsr   rg   rN   r!   r"   r#   r   r      sN    "F "D!KEMJ++NM"11NG8r"   r   c                   P    \ rS rSrSrS rSr\" S5      rSr	\
R                  rSrSrg)	r   i(  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   r!   N)rA   rB   rC   rD   rE   rj   rk   r   r3   rl   r   r   r   rN   r!   r"   r#   r   r   (  s3    "F  DKnEM //NGr"   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
    )rj   wrappedrr   r3   rs   c                       \ rS rSrSrS rSrSr\" S5      r	\
R                  =rrSrS=rrSrS	r\S
 5       rS rS rSrg)r   it  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                     [         R                  " XR                  U S9u  p#U(       a>  U(       d  US S nO,US S US S :w  a   [         R                  R	                  U S5      eUSS  nU " X#S9$ )Nr-   r   z0first two digits of salt and checksum must matchr/   )r1   r2   r3   r   r   r4   s       r#   r8   django_des_crypt.from_string  sw    LLyy#>	 2AwbqS!W$ ff//FH H ab'C++r"   c                     U R                   nUS S U R                  -   nU R                  (       a!  [        R                  " U R
                  X5      $ [        R                  " U R
                  SU5      $ )Nr    )r)   r0   use_duplicate_saltr1   r<   r3   )r>   r)   r7   s      r#   r?   django_des_crypt.to_string  sV    yy2Ah&""==T77 ==R55r"   c                     [         c
  [        5         U R                  (       a  U R                  U5        [        U R                  S S S9R                  U5      $ )Nr   )r)   )r   r$   use_defaults_check_truncate_policyr)   rg   re   s     r#   rg   django_des_crypt._calc_checksum  sG     ''/diim,;;FCCr"   r!   N)rA   rB   rC   rD   rE   rj   rk   rF   r   r3   r1   HASH64_CHARSrL   rJ   rl   r   rG   truncate_sizer   rM   r8   r?   rg   rN   r!   r"   r#   r   r   t  si    : DK:LhKE"$//1NZM())M%M , ,$6	Dr"   r   c                   V    \ rS rSrSrS r\" S5      rSr\	S 5       r
S r\	S 5       rSrg	)
r   i  a  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.
!r]   c                 d    [         R                  " U5      nUR                  U R                  5      $ r;   )r1   rz   r{   _hash_prefixr}   s     r#   r~   django_disabled.identify  s'    ))$/s//00r"   c                 F    [        [        [        S S U R                  5      $ )N)r   r   r   suffix_lengthre   s     r#   rg   django_disabled._calc_checksum  s    #|CR0$2D2DEEr"   c                     [         R                  " U5        U R                  U5      (       d  [         R                  R	                  U 5      egry   )r1   validate_secretr~   r   r   )r5   rf   r6   s      r#   verifydjango_disabled.verify  s7    
6"||D!!&&))#..r"   r!   N)rA   rB   rC   rD   rE   rj   r   r   r   rM   r~   rg   r   rN   r!   r"   r#   r   r     sJ    , DS6LM 1 1F  r"   r   )?rE   base64r   binasciir   hashlibr   r   r   logging	getLoggerrA   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handlersr1   __all__r   r$   rI   HasSaltGenericHandlerr'   	HasRoundsrP   r   r   PrefixWrapperr   rk   _using_clone_attrsru   r   r   usingr   TruncateMixinr   ifcDisabledHashStaticHandlerr   r!   r"   r#   <module>r      s   ;
   % % g''1 4 C C 5 5 - I I - # #	  	 N

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