
     h              
          d Z ddlmZmZ ddlZ ej
                  e      ZddlZddl	Z	ddl
mZ dZdaddlmZ ddlmZ ddlmZmZmZ ddlmZmZ dd	lmZmZmZmZmZ ddlm c m!Z" d
gZ# ed      Z$ ed      Z% ed      Z&e&e$e%fZ' e(e'      Z)dZ*	 ddl+Z e,ed      sdZ*dZn e,ed      sdZ*dZ	  e,ed      r( ej\                         Z/ej`                  jb                  Z2n G d d      Z3 e3       Z/dZ2 G d de"jh                  e"jj                  e"jl                  e"jn                  e"jp                  e"jr                        Z: G d de:      Z; G d de:      Z< G d de:      Z= G d d
e;e:      Z+y# e-$ r dZY w xY w)a  passlib.handlers.argon2 -- argon2 password hash wrapper

References
==========
* argon2
    - home: https://github.com/P-H-C/phc-winner-argon2
    - whitepaper: https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf
* argon2 cffi wrapper
    - pypi: https://pypi.python.org/pypi/argon2_cffi
    - home: https://github.com/hynek/argon2_cffi
* argon2 pure python
    - pypi: https://pypi.python.org/pypi/argon2pure
    - home: https://github.com/bwesterb/argon2pure
    )with_statementabsolute_importN)warn)exc)
MAX_UINT32)classpropertyto_bytesrender_bytes)b64s_encodeb64s_decode)uunicodebascii_to_struascii_to_strPY2argon2ididTypezb'argon2' module points to unsupported 'argon2' pypi package; please install 'argon2-cffi' instead.	low_levelz@'argon2-cffi' is too old, please update to argon2_cffi >= 18.2.0PasswordHasherc                   $    e Zd ZdZdZdZdZdZdZy)_DummyCffiHashera  
        dummy object to use as source of defaults when argon2_cffi isn't present.
        this tries to mimic the attributes of ``argon2.PasswordHasher()`` which the rest of
        this module reads.

        .. note:: values last synced w/ argon2 19.2 as of 2019-11-09
           i      N)	__name__
__module____qualname____doc__	time_costmemory_costparallelismsalt_lenhash_len     Y/var/www/html/Resume-Scraper/venv/lib/python3.12/site-packages/passlib/handlers/argon2.pyr   r   ]   s"    	 	r'   r      c                       e Zd ZdZdZdZej                  Ze	j                  j                  dz   Ze	j                  j                  dz   Zej                  ZdZeZej$                  ZdZeZdZd	ZeZd
ZdZdZdZi Zed        Z e!Z"ejF                  Z#eZ$ejJ                  Z%e&d        Z'd
Z(e)	 	 d fd	       Z*e)d        Z+ e,jZ                  d      Z.e)d        Z/ e,jZ                  de,j`                        Z1e)d        Z2d Z3d  fd	Z4e)d        Z5e)d        Z6e)d!d       Z7e)d        Z8 fdZ9dZ:e)d        Z;e)d"d       Z< xZ=S )#_Argon2Commona&  
    Base class which implements brunt of Argon2 code.
    This is then subclassed by the various backends,
    to override w/ backend-specific methods.

    When a backend is loaded, the bases of the 'argon2' class proper
    are modified to prepend the correct backend-specific subclass.
    r   )
salt	salt_sizer$   roundsr!   r"   r#   digest_sizer%   type)r0   )r$   r!   r%   r/         lineari NFc                 L    | j                          t        | j                        S )zj
        return tuple of types supported by this backend
        
        .. versionadded:: 1.7.2
        )get_backendtuple_backend_type_map)clss    r(   type_valuesz_Argon2Common.type_values   s     	S**++r'   c                 (    | j                   t        k(  S )zn
        flag indicating a Type D hash

        .. deprecated:: 1.7.2; will be removed in passlib 2.0
        )r0   TYPE_Dselfs    r(   type_dz_Argon2Common.type_d   s     yyF""r'   c	                 
   |d|	v rt        d      ||	d<   |d|	v rt        d      ||	d<   ||t        d      |}||t        d      |}t        t        |   di |	}
||
j	                  |      |
_        |	j                  d      }|It        |t        j                        rt        |      }t        j                  |
|dt        d	|
      |
_        |=t        |t        j                        rt        |      }|
j                  ||      |
_        |
j!                  |
j                  |
j"                         |Et        |t        j                        rt        |      }|dk  r|dk7  rt%        d|fz        ||
_        |
S )Nr.   z/'time_cost' and 'rounds' are mutually exclusiver-   z1'salt_len' and 'salt_size' are mutually exclusivez3'hash_len' and 'digest_size' are mutually exclusivez8'checksum_size' and 'digest_size' are mutually exclusiverelaxedr   r/   )minmaxparamrA   )rA   r2   r4   z7max_threads (%d) must be -1 (unlimited), or at least 1.r&   )	TypeErrorsuperr+   using
_norm_typer0   get
isinstanceuhnative_string_typesintnorm_integerr   checksum_size_norm_memory_costr"   _validate_constraintsr#   
ValueErrormax_threads)r9   r0   r"   r$   r!   r/   rO   r%   rS   kwdssubclsrA   	__class__s               r(   rG   z_Argon2Common.using  s     4 QRR&DNd" STT (D& UVV"K$& Z[['K }c0848  ++D1FK ((9%"+r'='=>!+.#%??6;BT^9FPW$YF  "+r'='=>!+.!'!9!9+w!9!WF 	$$V%7%79K9KL "+r'='=>!+.Q;"#4 !Z"-"0 1 1!,Fr'   c                 P    d|z  }||k  rt        d| j                  |||fz        y )Nr1   zO%s: memory_cost (%d) is too low, must be at least 8 * parallelism (8 * %d = %d))rR   name)r9   r"   r#   min_memory_costs       r(   rQ   z#_Argon2Common._validate_constraintsB  sD     k/( =!hh)?<< = = )r'   z^\$argon2[a-z]+\$c                 f    t        j                  |      }| j                  j                  |      d uS N)rK   to_unicode_for_identify_ident_regexmatch)r9   hashs     r(   identifyz_Argon2Common.identifyT  s.    ))$/%%d+477r'   s  
        ^
        \$argon2(?P<type>[a-z]+)\$
        (?:
            v=(?P<version>\d+)
            \$
        )?
        m=(?P<memory_cost>\d+)
        ,
        t=(?P<time_cost>\d+)
        ,
        p=(?P<parallelism>\d+)
        (?:
            ,keyid=(?P<keyid>[^,$]+)
        )?
        (?:
            ,data=(?P<data>[^,$]+)
        )?
        (?:
            \$
            (?P<salt>[^$]+)
            (?:
                \$
                (?P<digest>.+)
            )?
        )?
        $
    c                 :   t        |t              r|j                  d      }t        |t              st	        j
                  |d      | j                  j                  |      }|st	        j                  |       |j                  ddddddd	d
d	      \	  }}}}}}}	}
}|rt        d       | |j                  d      |rt        |      ndt        |      t        |      t        |      |
rt        |
      nd |	rt        |	      nd |rt        |            S d       S )Nutf-8r_   r0   versionr"   r!   r#   keyiddatar,   digestz&argon2 'keyid' parameter not supportedasciir   )r0   rc   r"   r.   r#   r,   re   checksum)rJ   r   encodebytesr   ExpectedStringError_hash_regexr^   MalformedHashErrorgroupNotImplementedErrordecoderM   r   )r9   r_   mr0   rc   r"   r!   r#   rd   re   r,   rf   s               r(   from_stringz_Argon2Common.from_string  s    dG$;;w'D$&))$77OO!!$'((--GGFI}k=VVX7 	Vg{I{E4v %&NOOW%$+CLK(y>K(&*T"&*T",2[(	
 		
 9=	
 		
r'   c                    | j                   }|dk(  rd}nd|z  }| j                  }|r"dt        t        | j                              z   }nd}dt	        | j
                        || j                  | j                  | j                  |t        t        | j                              t        t        | j                              fz  S )Nr    zv=%d$z,data=z"$argon2%s$%sm=%d,t=%d,p=%d%s$%s$%s)rc   re   r   r   r   r0   r"   r.   r#   r,   rh   )r>   rc   vstrre   kdstrs        r(   	to_stringz_Argon2Common.to_string  s    ,,d?DW$Dyy}[-CDDEE 4$))$KK+dii01+dmm45	7
 	
 		
r'   c                    |rt        d       |J t        }|j                  d      }|t        |      | _        t        t        |   d	i | |/t        j                  | | j                  | j                  d      sJ | j                  |      | _
        |/t        j                  | | j                  | j                  d      sJ | j                  |      | _        |/t        j                  | | j                  | j                  d      sJ | j                  |      | _        || j                   J y t#        |t$              s!t        j&                  j)                  |dd      || _        y )
Nzoargon2 `type_d=True` keyword is deprecated, and will be removed in passlib 2.0; please use ``type="d"`` insteadrh   r0   )rD   rc   r"   rj   re   r&   )r   r<   rI   lenrO   rF   r+   __init__rK   validate_default_valuer0   rH   rc   _norm_versionr"   rP   re   rJ   rj   r   ExpectedTypeError)	r>   r0   r?   rc   r"   re   rT   rh   rV   s	           r(   rz   z_Argon2Common.__init__  sX     3 4<D 88J'!$XD 	mT+3d3 <,,T499dooU[\\-DI ?,,T4<<ASAS3<> >  --g6DL ,,T43C3CTE[E[3@B B  $55kBD <99$$$dE*ff..tWfEEDIr'   c                    t        |t              sIt        r"t        |t              r|j	                  d      }n!t
        j                  j                  |dd      |t        v r|S |j                         }|t        v r|S t        d|      )Nrg   strr0   zunknown argon2 hash type: )rJ   r   r   rj   rp   rK   r   r}   ALL_TYPES_SETlowerrR   )r9   valuetemps      r(   rH   z_Argon2Common._norm_type  sz     %)z%/W-ff..ueVDD M!L {{}= K 5BCCr'   c                 8   t        |t        j                        s!t        j                  j	                  |dd      |dk  r|dk7  rt        d|fz        | j                         }|| j                  kD  r&t        d| j                  ||| j                  fz        |S )Nintegerrc   r)   r   zinvalid argon2 hash version: %dzk%s: hash version 0x%X not supported by %r backend (max version is 0x%X); try updating or switching backends)	rJ   rK   	int_typesr   r}   rR   r6   max_versionrX   )r9   rc   backends      r(   r|   z_Argon2Common._norm_version	  s    '2<<0&&**7IyII T>go>'KLL //#S__$ Y!hh#//JK L L r'   c                 J    t        j                  | || j                  d|      S )Nr"   )rB   rD   rA   )rK   rN   rY   )r9   r"   rA   s      r(   rP   z_Argon2Common._norm_memory_cost  s&    sKS5H5H%2GE 	Er'   c                     	 | j                   |   S # t        $ r Y nw xY wd|d| j                         d}t        |      )z>
        helper to resolve backend constant from type
        zunsupported argon2 hash (type z not supported by z	 backend))r8   KeyErrorr6   rR   )r9   r   msgs      r(   _get_backend_typez_Argon2Common._get_backend_type%  sL    
	((// 		 coo')os    	c                 N   t        |       }| j                   |j                   k7  ry|j                  }|||j                  kD  r|j                  }| j                  |k  ry| j                  |j                  k7  ry| j
                  |j
                  k7  ryt        t        | "  di |S )NTr&   )	r0   min_desired_versionr   rc   r"   rO   rF   r+   _calc_needs_update)r>   rT   r9   minverrV   s       r(   r   z _Argon2Common._calc_needs_update7  s    4j99 ((>Vcoo5__F<<& s.!2!22]D<DtDDr'   z> -- recommend you install one (e.g. 'pip install argon2_cffi')c                 J   | j                   }t        |t              r|dk\  sJ |dk  r't        d|z  t        j
                  j                         t        D ]  }|| j                  v s|| _	         y t        d|z  t        j
                  j                         t        | _	        y)z
        helper called by from backend mixin classes' _load_backend_mixin() --
        invoked after backend imports have been loaded, and performs
        feature detection & testing common to all backends.
        r   r)   z6%r doesn't support argon2 v1.3, and should be upgradedz)%r lacks support for all known hash typesT)r   rJ   rM   r   rK   r   PasslibSecurityWarning	ALL_TYPESr8   r0   PasslibRuntimeWarningTYPE_ID)	mixin_clsrX   dryrunr   r0   s        r(   _finalize_backend_mixinz%_Argon2Common._finalize_backend_mixinM  s      +++s+t0CCIDP..0  	%Dy222!%	 	%
 <tCRVVEaEab$INr'   c                 L   | j                         }||| j                  |      }|B|j                  |j                  |j                         |dk(  r|j
                  t        d      t        |      }|dvr|d|d|}nt        |      }t        j                  | |      )z}
        internal helper invoked when backend has hash/verification error;
        used to adapt to passlib message.
        argon2_cffiz8argon2_cffi backend doesn't support the 'data' parameter)zDecoding failedz reported: z: hash=)reason)r6   rr   rQ   r"   r#   re   ro   r   reprr   rm   )r9   errr_   r>   r   textr   s          r(   _adapt_backend_errorz"_Argon2Common._adapt_backend_errorg  s     //# <D,??4(D &&t'7'79I9IJ -'DII,A)*dee 3x   4;D$GF$ZF$$S88r'   )NNNNNNNN)NFNNN)F)NN)>r   r   r   r    rX   setting_kwds_default_settingsr%   rO   rK   GenericHandler_always_parse_settings_unparsed_settingsr$   default_salt_sizemin_salt_sizer   max_salt_sizer!   default_rounds
min_rounds
max_roundsrounds_costmax_parallelism_default_versionr   r   rY   rS   pure_use_threadsr8   r   r:   r   r0   r#   rc   r"   propertyr?   re   classmethodrG   rQ   recompiler]   r`   Xrl   rr   rw   rz   rH   r|   rP   r   r   _no_backend_suggestionr   r   __classcell__rV   s   @r(   r+   r+   s   s3     D
L0 &..M  ..EE&' **==MN *22MM '00NJJK
 $O #K  O K 
 , , D $//K G $//K# # D [_=A9 9v = = 2::23L8 82 "** 6 
7K: 
 
4
8,d D D(    E E  "E( ^ 2 9 9r'   r+   c                        e Zd ZdZed        Zed        Z ej                  dd      ed               Z	 fdZ
 xZS )	
_NoBackendz
    mixin used before any backend has been loaded.
    contains stubs that force loading of one of the available backends.
    c                 D    | j                          | j                  |      S r[   )_stub_requires_backendr_   )r9   secrets     r(   r_   z_NoBackend.hash  s    ""$xxr'   c                 F    | j                          | j                  ||      S r[   )r   verify)r9   r   r_   s      r(   r   z_NoBackend.verify  s    ""$zz&$''r'   z1.7z2.0)
deprecatedremovedc                 F    | j                          | j                  ||      S r[   )r   genhash)r9   r   configs      r(   r   z_NoBackend.genhash  s!     	""${{66**r'   c                 J    | j                          t        t        |   |      S r[   )r   rF   r   _calc_checksum)r>   r   rV   s     r(   r   z_NoBackend._calc_checksum  s%     	##% VT1&99r'   )r   r   r   r    r   r_   r   rK   deprecated_methodr   r   r   r   s   @r(   r   r     se         ( ( RUE:+  ;+: :r'   r   c                   t    e Zd ZdZed        Zed        Z ed eD              Z	ed        Z
ed        Zd Zy)	_CffiBackendz
    argon2_cffi backend
    c                    | t         u sJ t         t        rt        j                  t              yt        j
                  j                  }t        j                  dt        j                  |       t        j                  }i }t        D ]   }	 t        ||j                               ||<   " || _        |x| _        | _        | j)                  ||      S # t        $ r |t        t         fvs
J d|z         Y mw xY w)NFzOdetected 'argon2_cffi' backend, version %r, with support for 0x%x argon2 hashesunexpected missing type: %r)r   _argon2_cffi_argon2_cffi_errorr   PasslibSecurityErrorr   ARGON2_VERSIONlogdebug__version__r   r   getattrupperAttributeErrorTYPE_Ir<   r8   rc   r   r   )r   rX   r   r   TypeEnumtype_mapr0   s          r(   _load_backend_mixinz _CffiBackend._load_backend_mixin  s     L(( !../ABB",,;;		c**K	9  $$ 	ZDZ!(4::<!@	Z '/	# 5@?	I100v>> " ZFF#33Y5RUY5YY3Zs   C!C65C6c                    t        j                  |       t        |d      }	 t        t        j
                  j                  | j                  | j                        | j                  | j                  | j                  t        | j                               | j                  |            S # t        j                  j                  $ r}| j!                  |      d }~ww xY w)Nrb   )r0   r"   r!   r#   r,   r%   r   )rK   validate_secretr	   r   r   r   hash_secretr   r0   r"   r   r#   _generate_saltrO   
exceptionsHashingErrorr   )r9   r   r   s      r(   r_   z_CffiBackend.hash  s     	6"&'*	0 !7!7!C!C**3884OO,,OOc0023** "D "   &&33 	0**3//	0s   BB* *CCCc              #   V   K   | ]!  }t        d |j                  d            |f # yw)s
   $argon2%s$rg   N)r
   ri   ).0r0   s     r(   	<genexpr>z_CffiBackend.<genexpr>  s-      2# )G8LMtT 2s   ')c           	         t        j                  |       t        |d      }t        |d      }| j                  j	                  |d d|j                  dd      z    t              }| j                  |      }	 t        j                  j                  |||      }|du sJ y# t        j                  j                  $ r Y yt        j                  j                  $ r}| j                  ||      d }~ww xY w)Nrb   rg   r2      $TFr_   )rK   r   r	   _byte_ident_maprI   findr   r   r   r   verify_secretr   VerifyMismatchErrorVerificationErrorr   )r9   r   r_   r0   	type_coderesultr   s          r(   r   z_CffiBackend.verify  s     	6"&'*g& ""&&t,AQtyyq/A-A'BFK))$/		;!++99$	RFT>!&&:: 	&&88 	;**3T*::	;s   6'B C1=C1C,,C1c                 :   t        j                  |       t        |d      }| j                  |      }	 t	        t
        j                  j                  | j                  |j                        |j                  |j                  |j                  t        |j                        |j                  ||j                              }|j                  dk(  r|j'                  dd      }|S # t
        j                   j"                  $ r}| j%                  ||      d }~ww xY w)Nrb   )r0   r"   r!   r#   r,   r%   r   rc   r   r   z$v=16$$)rK   r   r	   rr   r   r   r   r   r   r0   r"   r.   r#   r,   rO   rc   r   r   r   replace)r9   r   r   r>   r   r   s         r(   r   z_CffiBackend.genhash  s     	6"&'*v&	="<#9#9#E#E**4995 ,,++ ,,dii(++ $F 	$ 	F <<4^^Hc2F &&33 	=**3V*<<	=s   BC% %DDDc                     t        d      )Nz-shouldn't be called under argon2_cffi backend)AssertionError)r>   r   s     r(   r   z_CffiBackend._calc_checksum*  s    LMMr'   N)r   r   r   r    r   r   r_   dictr   r   r   r   r   r&   r'   r(   r   r     sv     ? ?> 0 0&  2'02 2O ; ;,  6Nr'   r   c                   &    e Zd ZdZed        Zd Zy)_PureBackendz
    argon2pure backend
    c                    | t         u sJ 	 dd la	 ddlm} t
        j                  d|       |st        dt        j                         i }t        D ]'  }	 t        t        d|j                         z         ||<   ) || _        |x| _        | _        | j)                  ||      S # t        $ r Y yw xY w# t        $ r t
        j                  d       Y yw xY w# t        $ r |t        t         fvs
J d|z         Y w xY w)	Nr   F)ARGON2_DEFAULT_VERSIONz\detected 'argon2pure' backend, but package is too old (passlib requires argon2pure >= 1.2.3)zBdetected 'argon2pure' backend, with support for 0x%x argon2 hasheszUsing argon2pure backend, which is 100x+ slower than is required for adequate security. Installing argon2_cffi (via 'pip install argon2_cffi') is strongly recommendedARGON2r   )r   
argon2pure_argon2pureImportErrorr   r   warningr   r   r   r   r   r   r   r   r   r<   r8   rc   r   r   )r   rX   r   r   r   r0   s         r(   r   z _PureBackend._load_backend_mixin<  s     L((	,
	H 			V	  +,/,F,FH
  	ZDZ!(h6M!N	Z '/	#4??	I100v>>=  		  	KK A B	$ " ZFF#33Y5RUY5YY3Zs4   B" B1 $C"	B.-B.1CC!C98C9c                 0   t        j                  |       t        |d      }t        || j                  | j
                  | j                  | j                  | j                  | j                  | j                        | j                        }| j                  dkD  r| j                  |d<   | j                  rd|d<   | j                  r| j                  |d<   	 t        j                   d	i |S # t        j"                  $ r}| j%                  ||       d }~ww xY w)
Nrb   )passwordr,   r!   r"   r#   
tag_lengthr   rc   r   threadsTuse_threadsassociated_datar=   r&   )rK   r   r	   r   r,   r.   r"   r#   rO   r   r0   rc   rS   r   re   r   r   Argon2Errorr   )r>   r   rT   r   s       r(   r   z_PureBackend._calc_checksumn  s    
6"&'*kk(((()),,TYY7LL	
 a"..DO  "&D99&*iiD"#	<%%---&& 	<++Cd+;;	<s   C* *D=DDN)r   r   r   r    r   r   r   r&   r'   r(   r   r   4  s!     &? &?b<r'   r   c                   $    e Zd ZdZdZdZeeedZ	y)r   a	  
    This class implements the Argon2 password hash [#argon2-home]_, and follows the :ref:`password-hash-api`.

    Argon2 supports a variable-length salt, and variable time & memory cost,
    and a number of other configurable parameters.

    The :meth:`~passlib.ifc.PasswordHash.replace` method accepts the following optional keywords:

    :type type: str
    :param type:
        Specify the type of argon2 hash to generate.
        Can be one of "ID", "I", "D".

        This defaults to "ID" if supported by the backend, otherwise "I".

    :type salt: str
    :param salt:
        Optional salt string.
        If specified, the length must be between 0-1024 bytes.
        If not specified, one will be auto-generated (this is recommended).

    :type salt_size: int
    :param salt_size:
        Optional number of bytes to use when autogenerating new salts.

    :type rounds: int
    :param rounds:
        Optional number of rounds to use.
        This corresponds linearly to the amount of time hashing will take.

    :type time_cost: int
    :param time_cost:
        An alias for **rounds**, for compatibility with underlying argon2 library.

    :param int memory_cost:
        Defines the memory usage in kibibytes.
        This corresponds linearly to the amount of memory hashing will take.

    :param int parallelism:
        Defines the parallelization factor.
        *NOTE: this will affect the resulting hash value.*

    :param int digest_size:
        Length of the digest in bytes.

    :param int max_threads:
        Maximum number of threads that will be used.
        -1 means unlimited; otherwise hashing will use ``min(parallelism, max_threads)`` threads.

        .. note::

            This option is currently only honored by the argon2pure backend.

    :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.

    .. versionchanged:: 1.7.2

        Added the "type" keyword, and support for type "D" and "ID" hashes.
        (Prior versions could verify type "D" hashes, but not generate them).

    .. todo::

        * Support configurable threading limits.
    )r   r   T)Nr   r   N)
r   r   r   r    backends_backend_mixin_targetr   r   r   _backend_mixin_mapr&   r'   r(   r   r     s+    E` -H ! #"r'   )>r    
__future__r   r   logging	getLoggerr   r   r   typeswarningsr   r   r   passlibr   passlib.crypto.digestr   passlib.utilsr   r	   r
   passlib.utils.binaryr   r   passlib.utils.compatr   r   r   r   r   passlib.utils.handlersutilshandlersrK   __all__r   r<   r   r   setr   r   r   hasattrr   r   r   r   r   r   r   SubclassBackendMixinParallelismMixin	HasRounds
HasRawSaltHasRawChecksumr   r+   r   r   r   r&   r'   r(   <module>r     s  " 7 g! 	    , ? ? 9 N N # #   
3	
3
D' ff%	I  ! <(4 	 \;/_ <)*3335#--<<   )*
R9B++R-@-@LL"--1B1B%%R9v!: !:TsN= sNxT<= T<t[Z [Q  Ls   E1 1E;:E;