a
    Oʞh_W                     @   s$  d Z ddlZddlZee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Z ddlm  mZ g dZd	Zd
d Zdd Zdd Zdd Z G dd dej!ej"ej#ej$Z%G dd dej"ej&ej#ej$Z'G dd dej#ej$Z(G dd dej!ej#ej$Z)dS )zFpasslib.handlers.des_crypt - traditional unix (DES) crypt and variants    N)warn)
safe_crypt
test_crypt
to_unicode)h64h64big)byte_elem_valueuuascii_to_strunicodesuppress_cause)des_encrypt_int_block)	des_crypt
bsdi_cryptbigcryptcrypt16    c                 C   s   t dd t| dd D S )zconvert secret to 64-bit DES key.

    this only uses the first 8 bytes of the secret,
    and discards the high 8th bit of each byte at that.
    a null parity bit is inserted after every 7th bit of the output.
    c                 s   s*   | ]"\}}t |d @ d|d  > V  qdS )   9      N)r   ).0ic r   U/wd/webapps/venvs/v2025_4um/lib/python3.9/site-packages/passlib/handlers/des_crypt.py	<genexpr>(   s   z'_crypt_secret_to_key.<locals>.<genexpr>Nr   )sum	enumerate)secretr   r   r   _crypt_secret_to_key   s    r   c                 C   sp   t |dksJ t|}t| tr.| d} t| ts<J t| v rPtj	
tt| }t|d|d}t|S )z pure-python backed for des_crypt   utf-8r      )lenr   decode_int12
isinstancer   encodebytes_BNULLuhexcNullPasswordErrorr   r   r   r   encode_int64)r   salt
salt_value	key_valueresultr   r   r   _raw_des_crypt+   s    


r1   c                 C   sL   t | }d}t| }||k rH|d }t | || }t|||A }|}q|S )z,convert secret to DES key used by bsdi_cryptr   )r   r#   r   )r   r/   idxendnext	tmp_valuer   r   r   _bsdi_secret_to_keyI   s    r6   c                 C   s`   t |}t| tr| d} t| ts,J t| v r@tj	t
t| }t|d||}t|S )z"pure-python backend for bsdi_cryptr!   r   )r   decode_int24r%   r   r&   r'   r(   r)   r*   r+   r   r6   r   r   r,   )r   roundsr-   r.   r/   r0   r   r   r   _raw_bsdi_cryptU   s    


r9   c                   @   s   e Zd ZdZd ZdZejZdZ	d Z
ZejZdZeedejejB Zedd Zd	d
 Zdd ZdZedd Zdd Zedd Zdd ZdS )r   a  This class implements the des-crypt password hash, and follows the :ref:`password-hash-api`.

    It supports a fixed-length salt.

    The :meth:`~passlib.ifc.PasswordHash.using` method accepts 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, 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

    :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
        ``salt`` strings that are too long.

        .. versionadded:: 1.6
    r-   Ztruncate_error   r    r   zU
        ^
        (?P<salt>[./a-z0-9]{2})
        (?P<chk>[./a-z0-9]{11})?
        $c                 C   s6   t |dd}|d d |dd   }}| ||p0d dS )Nasciihashr    r-   checksum)r   )clsr=   r-   chkr   r   r   from_string   s    zdes_crypt.from_stringc                 C   s   t d| j| jf }t|S Nz%s%sr	   r-   r?   r
   selfr=   r   r   r   	to_string   s    zdes_crypt.to_stringc                 C   s   | j r| | | |S )N)use_defaults_check_truncate_policyZ_calc_checksum_backendrF   r   r   r   r   _calc_checksum   s    
zdes_crypt._calc_checksumZos_cryptbuiltinc                 C   s"   t ddr| | j dS dS d S )NtestZabgOeLfPimXQoTFr   _set_calc_checksum_backend_calc_checksum_os_cryptr@   r   r   r   _load_backend_os_crypt   s    
z des_crypt._load_backend_os_cryptc                 C   sT   t || j}|d u r| |S || jr6t|dkrHtj| | j||dd  S )N   r    )r   r-   _calc_checksum_builtin
startswithr#   r)   r*   CryptBackendError)rF   r   r=   r   r   r   rQ      s    
z!des_crypt._calc_checksum_os_cryptc                 C   s   |  | j dS NTrP   rU   rR   r   r   r   _load_backend_builtin   s    zdes_crypt._load_backend_builtinc                 C   s   t || jddS Nr<   )r1   r-   r&   decoderJ   r   r   r   rU      s    z des_crypt._calc_checksum_builtinN)__name__
__module____qualname____doc__namesetting_kwdsr)   HASH64_CHARSchecksum_charschecksum_sizemin_salt_sizemax_salt_size
salt_charstruncate_sizerecompiler	   XI_hash_regexclassmethodrB   rG   rK   backendsrS   rQ   rZ   rU   r   r   r   r   r   p   s,   $





r   c                       s   e Zd ZdZd ZdZdZejZ	d Z
ZejZdZdZdZdZeed	ejejB Zed
d Zdd ZdZe fddZe fddZ fddZdZedd Zdd Z edd Z!dd Z"  Z#S )r   a
  This class implements the BSDi-Crypt password hash, and follows the :ref:`password-hash-api`.

    It supports a fixed-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, one will be autogenerated (this is recommended).
        If specified, it must be 4 characters, drawn from the regexp range ``[./0-9A-Za-z]``.

    :type rounds: int
    :param rounds:
        Optional number of rounds to use.
        Defaults to 5001, must be between 1 and 16777215, inclusive.

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

        .. versionadded:: 1.6

    .. versionchanged:: 1.6
        :meth:`hash` will now issue a warning if an even number of rounds is used
        (see :ref:`bsdi-crypt-security-issues` regarding weak DES keys).
    )r-   r8   r;      i     i Zlinearz
        ^
        _
        (?P<rounds>[./a-z0-9]{4})
        (?P<salt>[./a-z0-9]{4})
        (?P<chk>[./a-z0-9]{11})?
        $c                 C   sV   t |dd}| j|}|s(tj| |ddd\}}}| t|	d||dS )Nr<   r=   r8   r-   rA   )r8   r-   r?   )
r   rn   matchr)   r*   InvalidHashErrorgroupr   r7   r&   )r@   r=   mr8   r-   rA   r   r   r   rB   4  s    zbsdi_crypt.from_stringc                 C   s,   t dt| jd| j| jf }t|S )Nz_%s%s%sr<   )r	   r   Zencode_int24r8   r\   r-   r?   r
   rE   r   r   r   rG   A  s    zbsdi_crypt.to_stringTc                    s2   t t| jf i |}|jd@ s.tdtjj |S )Nrr   zHbsdi_crypt rounds should be odd, as even rounds may reveal weak DES keys)superr   usingdefault_roundsr   r)   r*   ZPasslibSecurityWarning)r@   kwdssubcls	__class__r   r   rx   N  s    
zbsdi_crypt.usingc                    s   t t|  }|dB S )Nrr   )rw   r   _generate_rounds)r@   r8   r|   r   r   r~   W  s    zbsdi_crypt._generate_roundsc                    s$   | j d@ sdS tt| jf i |S )Nrr   T)r8   rw   r   _calc_needs_update)rF   rz   r|   r   r   r   e  s    
zbsdi_crypt._calc_needs_updaterL   c                 C   s"   t ddr| | j dS dS d S )NrN   z_/...lLDAxARksGCHin.TFrO   rR   r   r   r   rS   t  s    
z!bsdi_crypt._load_backend_os_cryptc                 C   s^   |   }t||}|d u r$| |S ||d d rBt|dkrRtj| |||dd  S )N	      )rG   r   rU   rV   r#   r)   r*   rW   )rF   r   configr=   r   r   r   rQ   |  s    

z"bsdi_crypt._calc_checksum_os_cryptc                 C   s   |  | j dS rX   rY   rR   r   r   r   rZ     s    z bsdi_crypt._load_backend_builtinc                 C   s   t || j| jddS r[   )r9   r8   r-   r&   r\   rJ   r   r   r   rU     s    z!bsdi_crypt._calc_checksum_builtin)$r]   r^   r_   r`   ra   rb   re   r)   rc   rd   rf   rg   rh   ry   Z
min_rounds
max_roundsZrounds_costrj   rk   r	   rl   rm   rn   ro   rB   rG   Z_avoid_even_roundsrx   r~   r   rp   rS   rQ   rZ   rU   __classcell__r   r   r|   r   r      s<   #





r   c                       sr   e Zd ZdZd ZdZejZd Z	Z
ejZeedejejB Zedd Zdd Zd fd
d	Zdd Z  ZS )r   ag  This class implements the BigCrypt password hash, and follows the :ref:`password-hash-api`.

    It supports a fixed-length salt.

    The :meth:`~passlib.ifc.PasswordHash.using` method accepts 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 22 characters, drawn from the regexp range ``[./0-9A-Za-z]``.

    :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
        ``salt`` strings that are too long.

        .. versionadded:: 1.6
    )r-   r    zX
        ^
        (?P<salt>[./a-z0-9]{2})
        (?P<chk>([./a-z0-9]{11})+)?
        $c                 C   sD   t |dd}| j|}|s(tj| |dd\}}| ||dS Nr<   r=   r-   rA   r>   r   rn   rs   r)   r*   rt   ru   r@   r=   rv   r-   rA   r   r   r   rB     s    zbigcrypt.from_stringc                 C   s   t d| j| jf }t|S rC   rD   rE   r   r   r   rG     s    zbigcrypt.to_stringFc                    s0   t t| j||d}t|d r,tj| |S )N)relaxedr;   )rw   r   _norm_checksumr#   r)   r*   rt   )rF   r?   r   r|   r   r   r     s    zbigcrypt._norm_checksumc                 C   sp   t |tr|d}t|| jd}d}t|}||k rf|d }|t||| |dd 7 }|}q2|dS )Nr!   r<   r   r   i)r%   r   r&   r1   r-   r#   r\   )rF   r   rA   r2   r3   r4   r   r   r   rK     s    

zbigcrypt._calc_checksum)F)r]   r^   r_   r`   ra   rb   r)   rc   rd   rf   rg   rh   rj   rk   r	   rl   rm   rn   ro   rB   rG   r   rK   r   r   r   r|   r   r     s   


	r   c                   @   sh   e Zd ZdZd ZdZdZejZ	d Z
ZejZdZeedejejB Zedd Zd	d
 Zdd ZdS )r   a  This class implements the crypt16 password hash, and follows the :ref:`password-hash-api`.

    It supports a fixed-length salt.

    The :meth:`~passlib.ifc.PasswordHash.using` method accepts 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, crypt16 will silently truncate passwords larger than 16 bytes.
        Setting ``truncate_error=True`` will cause :meth:`~passlib.ifc.PasswordHash.hash`
        to raise a :exc:`~passlib.exc.PasswordTruncateError` instead.

        .. versionadded:: 1.7

    :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
        ``salt`` strings that are too long.

        .. versionadded:: 1.6
    r:      r       zU
        ^
        (?P<salt>[./a-z0-9]{2})
        (?P<chk>[./a-z0-9]{22})?
        $c                 C   sD   t |dd}| j|}|s(tj| |dd\}}| ||dS r   r   r   r   r   r   rB   +  s    zcrypt16.from_stringc                 C   s   t d| j| jf }t|S rC   rD   rE   r   r   r   rG   4  s    zcrypt16.to_stringc                 C   s   t |tr|d}| jr$| | zt| jd}W n tyX   t	tdY n0 t
|}t|d|d}t
|dd }t|d|d}t|t| }|dS )	Nr!   r<   zinvalid chars in saltr   r   r   r      )r%   r   r&   rH   rI   r   r$   r-   
ValueErrorr   r   r   r   r,   r\   )rF   r   r.   key1Zresult1key2Zresult2rA   r   r   r   rK   ;  s    


zcrypt16._calc_checksumN)r]   r^   r_   r`   ra   rb   re   r)   rc   rd   rf   rg   rh   ri   rj   rk   r	   rl   rm   rn   ro   rB   rG   rK   r   r   r   r   r     s   $


r   )*r`   rj   logging	getLoggerr]   logwarningsr   Zpasslib.utilsr   r   r   Zpasslib.utils.binaryr   r   Zpasslib.utils.compatr   r	   r
   r   r   Zpasslib.crypto.desr   Zpasslib.utils.handlersutilshandlersr)   __all__r(   r   r1   r6   r9   ZTruncateMixinZHasManyBackendsZHasSaltZGenericHandlerr   Z	HasRoundsr   r   r   r   r   r   r   <module>   s(   
  $S