+
    iN                        R t ^ RIHt ^ RIHt ^ RIHtHtHt ^ RI	t	]	P                  ! ]4      t^ RIHt ^ RIHtHtHtHt ^ RIHtHtHt ^ RIHt ^ R	IHtHtHtHt ^ R
IH t  ^ RI!H"u H#t$ . R+Ot%Rs&R t'Rt( ! R R]$PR                  ]$PT                  4      t+ ! R R]$PX                  ]+4      t- ! R R]+4      t. ! R R]+4      t/]$P`                  ! R]]! R4      ]! R4      RR7      t1R]1n2        ]1;Pf                  R,,          un3         ! R R ]4      t4 ! R! R]-4      t5 ! R" R]54      t6]$P`                  ! R]Pn                  ! R#R$7      ]! R%4      ]! R&4      R'R(7      t8R%]8n2        ]8;Pf                  R,,          un3         ! R) R]$Pr                  ]$PR                  ]$PT                  4      t: ! R* R]$Pv                  Px                  ]$Pz                  4      t>R# )-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                  *    \         f   ^ RIH s  \         # )N)	des_crypt)r   passlib.hash     U/var/www/html/photoedit/myenv/lib/python3.14/site-packages/passlib/handlers/django.py_import_des_cryptr#   &   s    *r!   >abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789c                   b   a  ] tR t^2t o RtRt^tRt]t	]
P                  t]R 4       tR tRtV tR# )DjangoSaltedHashz2base class providing common code for django hashesNc                \    \         P                  ! WP                  V R 7      w  r#V ! W#R7      # )handlersaltchecksum)uh	parse_mc2identclshashr+   chks   &&  r"   from_stringDjangoSaltedHash.from_stringB   s#    LLyy#>	++r!   c                n    \         P                  ! V P                  V P                  V P                  4      # N)r-   
render_mc2r/   r+   r,   selfs   &r"   	to_stringDjangoSaltedHash.to_stringG   s!    }}TZZDMMBBr!   r    )r+   	salt_size)__name__
__module____qualname____firstlineno____doc__setting_kwdsdefault_salt_sizemax_salt_size
SALT_CHARS
salt_charsr-   LOWER_HEX_CHARSchecksum_charsclassmethodr4   r;   __static_attributes____classdictcell____classdict__s   @r"   r&   r&   2   sJ     < )L MJ''N, ,C Cr!   r&   c                   d   a  ] tR t^Kt o Rt]P                  R,           t^t]R 4       t	R t
RtV tR# )DjangoVariableHashzEbase class providing common code for django hashes w/ variable roundsc                `    \         P                  ! WP                  V R 7      w  r#pV ! W#VR7      # )r(   )roundsr+   r,   )r-   	parse_mc3r/   )r1   r2   rR   r+   r3   s   &&   r"   r4   DjangoVariableHash.from_stringQ   s(    LLyy#Fc&c::r!   c                    \         P                  ! V P                  V P                  V P                  V P
                  4      # r7   )r-   
render_mc3r/   rR   r+   r,   r9   s   &r"   r;   DjangoVariableHash.to_stringV   s'    }}TZZdiiOOr!   r    N)rR   )r>   r?   r@   rA   rB   r&   rC   
min_roundsrJ   r4   r;   rK   rL   rM   s   @r"   rP   rP   K   s;     O#00;>LJ; ;P Pr!   rP   c                   F   a  ] tR t^Yt o RtR tRt]! R4      t^(t	R t
RtV tR# )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                    \        V\        4      '       d   VP                  R 4      p\        \	        V P
                  P                  R4      V,           4      P                  4       4      # 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r>   r?   r@   rA   rB   namedjango_namer   r/   checksum_sizerc   rK   rL   rM   s   @r"   r   r   Y   s0     4  DKgJEMS Sr!   c                   F   a  ] tR t^~t o RtR tRt]! R4      t^ t	R t
RtV tR# )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                    \        V\        4      '       d   VP                  R 4      p\        \	        V P
                  P                  R4      V,           4      P                  4       4      # r[   )r^   r   r_   r   r   r+   r`   ra   s   &&r"   rc    django_salted_md5._calc_checksum   sJ    fg&&]]7+FS!1!1'!:V!CDNNPQQr!   r    Nre   rM   s   @r"   r   r   ~   s0     6 DKfIEM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
    )prefixr/   docr	   c                      a a ] tR t^t oRtR tRt]t]	! R4      t
]R 4       t]V 3R l4       tV 3R ltV 3R ltRtVtV ;t# )	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                x    \         P                  ! V4      pV'       g   R # VP                  V P                  4      # F)r-   to_unicode_for_identify
startswithdjango_prefixr1   r2   s   &&r"   identifydjango_bcrypt_sha256.identify   s-    ))$/s0011r!   c                `  < \        VR R4      pVP                  V P                  4      '       g    \        P                  P                  V 4      hV\        V P                  4      R pVP                  R4      '       g    \        P                  P                  V 4      h\        \        V `+  V4      # )r]   r2   Nz$2)r   rt   ru   r-   excInvalidHashErrorlenMalformedHashErrorsuperro   r4   )r1   r2   bhash	__class__s   && r"   r4    django_bcrypt_sha256.from_string   s    $0s0011&&))#..S**+,-%%&&++C00)3;EBBr!   c                `   < \         \        V `  4       p\        V P                  4      V,           # r7   )r~   ro   r;   r   ru   )r:   r   r   s   & r"   r;   django_bcrypt_sha256.to_string   s)    *D;=T//0588r!   c                   < \        V\        4      '       d   VP                  R 4      p\        V P	                  V4      P                  4       4      p\        \        V `#  V4      # )r\   )	r^   r   r_   r   _digestdigestr~   ro   rc   )r:   rb   r   s   &&r"   rc   #django_bcrypt_sha256._calc_checksum   sM    fg&&]]7+Ff-4467)4?GGr!   r    )r>   r?   r@   rA   rB   rf   rg   r   r   r   ru   rJ   rw   r4   r;   rc   rK   rL   __classcell__)r   rN   s   @@r"   ro   ro      sa     	 "D!KG &'M2 2 C C9H Hr!   ro   c                      a  ] tR t^t o RtR tRt]! R4      t^t	Rt
]P                  t^,t]P                   tRtR tRtV tR# )	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$l    r   c                    \        V P                  WP                  V P                  4      p\	        V4      P                  4       P                  R 4      # )r]   )r   r   r+   rR   r   rstripdecode)r:   rb   r2   s   && r"   rc   #django_pbkdf2_sha256._calc_checksum#  s:    4<<DKKH%%'..w77r!   r    N)r>   r?   r@   rA   rB   rf   rg   r   r/   min_salt_size
max_roundsr-   PADDED_BASE64_CHARSrI   rh   r   default_roundsr   rc   rK   rL   rM   s   @r"   r   r      sV     "F "D!KEMJ++NM"11NG8 8r!   c                   R    ] tR tRtRtR tRt]! R4      t^t	]
P                  tRtRtR# )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)r>   r?   r@   rA   rB   rf   rg   r   r/   rh   r
   r   r   rK   r    r!   r"   r   r   (  s3    "F  DKnEM //NGr!   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
    )rf   wrappedrl   r/   rm   c                      a  ] tR tRt o RtR tRtRt]! R4      t	]
P                  ;tt^t^;tt^tRt]R 4       tR tR tR	tV tR
# )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.
cryptzcrypt$Tc                   \         P                  ! WP                  V R 7      w  r#V'       dQ   V'       g   VR,          pM5VR,          VR,          8w  d!   \         P                  P	                  V R4      hVR,          pV ! W#R7      # )r(   N   Nz0first two digits of salt and checksum must match:r   NNr*   )r-   r.   r/   rz   r}   r0   s   &&  r"   r4   django_des_crypt.from_string  so    LLyy#>	 2wbSW$ ff//FH H b'C++r!   c                    V P                   pVR ,          V P                  ,           pV P                  '       d"   \        P                  ! V P
                  W4      # \        P                  ! V P
                  RV4      # )r    )r+   r,   use_duplicate_saltr-   r8   r/   )r:   r+   r3   s   &  r"   r;   django_des_crypt.to_string  sW    yy2h&"""==T77 ==R55r!   c                    \         f   \        4        V P                  '       d   V P                  V4       \        V P                  R,          R7      P                  V4      # )Nr   )r+   )r   r#   use_defaults_check_truncate_policyr+   rc   ra   s   &&r"   rc   django_des_crypt._calc_checksum  sH     ''/diim,;;FCCr!   r    N)r+   r=   truncate_error)r>   r?   r@   rA   rB   rf   rg   rC   r   r/   r-   HASH64_CHARSrI   rG   rh   r   rD   truncate_sizer   rJ   r4   r;   rc   rK   rL   rM   s   @r"   r   r   t  sr     : DK:LhKE"$//1NZM())M%M , ,$6	D 	Dr!   c                   b   a  ] tR tRt o RtR t]! R4      t^(t]	R 4       t
R t]	R 4       tRtV tR# )	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.
!c                d    \         P                  ! V4      pVP                  V P                  4      # r7   )r-   rs   rt   _hash_prefixrv   s   &&r"   rw   django_disabled.identify  s'    ))$/s//00r!   c                F    \        \        \        R R V P                  4      # )N)r   r   r   suffix_lengthra   s   &&r"   rc   django_disabled._calc_checksum  s    #|CR0$2D2DEEr!   c                    \         P                  ! V4       V P                  V4      '       g    \         P                  P	                  V 4      hR # rr   )r-   validate_secretrw   rz   r{   )r1   rb   r2   s   &&&r"   verifydjango_disabled.verify  s7    
6"||D!!&&))#..r!   r    N)r>   r?   r@   rA   rB   rf   r   r   r   rJ   rw   rc   r   rK   rL   rM   s   @r"   r   r     sM     , DS6LM 1 1F  r!   )r   r   r   r   r   r   r   r   )rg   )?rB   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handlersr-   __all__r   r#   rF   HasSaltGenericHandlerr&   	HasRoundsrP   r   r   PrefixWrapperr   rg   _using_clone_attrsro   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!   