
Ѯhz                 @   s  d  Z  d d l m Z m Z 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 Z e j e  Z d d l m Z d d l m Z m Z m Z m Z m Z m Z m Z m Z m  Z  m! Z! m" Z" m# Z# d d l$ m% Z% d	 d
 d d d d d d d d d d d d d d d d d d d g Z& e! d  Z' e! d  Z( e! d   Z) e! d!  Z* e' e! d"  Z+ e! d#  Z, e! d$  Z- e! d%  Z. e e d&   Z/ d' Z0 d( Z1 d) Z2 e3 e e/   Z4 d d* d  Z5 d+ d   Z6 d, d   Z7 d- Z8 d) Z9 d. Z: d/ d   Z; d0 d   Z< d1 d   Z
 e5 d2 d3 d4 d5 i  Z= e2 d6 Z> d7 d   Z Gd8 d   d e?  Z@ Gd9 d   d e@  ZA eA e)  ZB eA e) d: d; ZC eA e* d: d; ZD d S)<zC
passlib.utils.binary - binary data encoding/decoding/manipulation
    )absolute_importdivisionprint_function)	b64encode	b64decode	b32decode	b32encode)
b2a_base64
a2b_base64ErrorN)exc)PY3bascii_to_strirangeimapiter_byte_charsjoin_byte_valuesjoin_byte_elems
nextgettersuppress_causeuunicodeunicode_or_bytes_types)memoized_propertyBASE64_CHARSPADDED_BASE64_CHARS
AB64_CHARSHASH64_CHARSBCRYPT_CHARS	HEX_CHARSLOWER_HEX_CHARSUPPER_HEX_CHARSALL_BYTE_VALUEScompile_byte_translationab64_encodeab64_decodeb64s_encodeb64s_decoder   r   Base64EngineLazyBase64Engineh64h64bigbcrypt64z@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/z@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./z@./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzz@./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789=Z0123456789abcdefABCDEFZ0123456789ABCDEFZ0123456789abcdef       s       =c             C   s  | d k r t  d d  } n9 t | t  r@ t |  d k sF t  t t |   } x |  j   D] \ } } t | t  r t	 |  } t | t
  r d | k o d k  n s t  t | t  r | j d  } t | t  r t |  d k st  | | | <qe Wt j |  S)a  
    return a 256-byte string for translating bytes using specified mapping.
    bytes not specified by mapping will be left alone.

    :param mapping:
        dict mapping input byte (str or int) -> output byte (str or int).

    :param source:
        optional existing byte translation string to use as base.
        (must be 255-length byte string).  defaults to identity mapping.

    :returns:
        255-length byte string for passing to bytes().translate.
    N   r   r.   ascii   )_TRANSLATE_SOURCE
isinstancebyteslenAssertionErrorlistr   itemsr   ordintr   encodeB_EMPTYjoin)mappingsourcetargetkv rE   ../../passlib/utils/binary.pyr#   n   s    '1'c             C   s   t  |   j t  S)zr
    encode using shortened base64 format which omits padding & whitespace.
    uses default ``+/`` altchars.
    )r	   rstrip_BASE64_STRIP)datarE   rE   rF   r&      s    c             C   s   t  |  t  rI y |  j d  }  Wn$ t k
 rH t t d    Yn Xt |   d @} | d k rh n> | d k r |  t 7}  n% | d k r |  t 7}  n t d   y t	 |   SWn7 t
 k
 r } z t t |    WYd d } ~ Xn Xd S)zq
    decode from shortened base64 format which omits padding & whitespace.
    uses default ``+/`` altchars.
    r2   z4string argument should contain only ASCII characters   r      zinvalid base64 inputN)r5   r   r=   UnicodeEncodeErrorr   
ValueErrorr7   _BASE64_PAD2_BASE64_PAD1r
   _BinAsciiError	TypeError)rI   offerrrE   rE   rF   r'      s"    s   =
s   ==c             C   s   t  |   j d d  S)z
    encode using shortened base64 format which omits padding & whitespace.
    uses custom ``./`` altchars.

    it is primarily used by Passlib's custom pbkdf2 hashes.
       +   .)r&   replace)rI   rE   rE   rF   r$      s    c             C   s_   t  |  t  rI y |  j d  }  Wn$ t k
 rH t t d    Yn Xt |  j d d   S)z
    decode from shortened base64 format which omits padding & whitespace.
    uses custom ``./`` altchars, but supports decoding normal ``+/`` altchars as well.

    it is primarily used by Passlib's custom pbkdf2 hashes.
    r2   z4string argument should contain only ASCII charactersrU   rT   )r5   r   r=   rL   r   rM   r'   rV   )rI   rE   rE   rF   r%      s    c             C   s   t  t |   j t   S)zh
    wrapper around :func:`base64.b32encode` which strips padding,
    and returns a native string.
    )r   
_b32encoderG   B_EQUAL)rA   rE   rE   rF   r      s    8B0O   c             C   se   t  |  t  r |  j d  }  |  j t  }  t |   d @} | rX |  t d |  7}  t |  d  S)z
    wrapper around :func:`base64.b32decode`
    which handles common mistyped chars.
    padding optional, ignored if present.
    r2      NT)r5   r   r=   	translate_b32_translater7   _b32_decode_pad
_b32decode)rA   Z	remainderrE   rE   rF   r      s    c               @   s  e  Z d  Z d Z d Z d Z d Z d Z d Z d Z	 d d d  Z
 e d d    Z d d	   Z d
 d   Z d d   Z d d   Z d d   Z d d   Z d d   Z e d d    Z e d d    Z d d   Z d d   Z d d   Z d  d!   Z d" d#   Z d$ d%   Z d& d'   Z d( d)   Z d* d+   Z d, d-   Z  d. d/   Z! d0 d1   Z" d2 d3   Z# d4 d5   Z$ d6 d7   Z% d8 d9   Z& d S):r(   ac  Provides routines for encoding/decoding base64 data using
    arbitrary character mappings, selectable endianness, etc.

    :arg charmap:
        A string of 64 unique characters,
        which will be used to encode successive 6-bit chunks of data.
        A character's position within the string should correspond
        to its 6-bit value.

    :param big:
        Whether the encoding should be big-endian (default False).

    .. note::
        This class does not currently handle base64's padding characters
        in any way what so ever.

    Raw Bytes <-> Encoded Bytes
    ===========================
    The following methods convert between raw bytes,
    and strings encoded using the engine's specific base64 variant:

    .. automethod:: encode_bytes
    .. automethod:: decode_bytes
    .. automethod:: encode_transposed_bytes
    .. automethod:: decode_transposed_bytes

    ..
        .. automethod:: check_repair_unused
        .. automethod:: repair_unused

    Integers <-> Encoded Bytes
    ==========================
    The following methods allow encoding and decoding
    unsigned integers to and from the engine's specific base64 variant.
    Endianess is determined by the engine's ``big`` constructor keyword.

    .. automethod:: encode_int6
    .. automethod:: decode_int6

    .. automethod:: encode_int12
    .. automethod:: decode_int12

    .. automethod:: encode_int24
    .. automethod:: decode_int24

    .. automethod:: encode_int64
    .. automethod:: decode_int64

    Informational Attributes
    ========================
    .. attribute:: charmap

        unicode string containing list of characters used in encoding;
        position in string matches 6bit value of character.

    .. attribute:: bytemap

        bytes version of :attr:`charmap`

    .. attribute:: big

        boolean flag indicating this using big-endian encoding.
    NFc             C   s
  t  | t  r! | j d  } n! t  | t  sB t j | d   t |  d k r` t d   t t |   d k r t d   | |  _	 | j
 |  _ t d d   t |  D  } | j
 |  _ | |  _ | r |  j |  _ |  j |  _ n |  j |  _ |  j |  _ d  S)Nzlatin-1charmap@   z'charmap must be 64 characters in lengthz-charmap must not contain duplicate charactersc             s   s!   |  ] \ } } | | f Vq d  S)NrE   ).0idxvaluerE   rE   rF   	<genexpr>]  s    z(Base64Engine.__init__.<locals>.<genexpr>)r5   r   r=   r6   r   ExpectedStringErrorr7   rM   setbytemap__getitem__	_encode64dict	enumerate	_decode64big_encode_bytes_big_encode_bytes_decode_bytes_big_decode_bytes_encode_bytes_little_decode_bytes_little)selfrc   rq   lookuprE   rE   rF   __init__Q  s$    		zBase64Engine.__init__c             C   s   |  j  j d  S)zcharmap as unicodezlatin-1)rk   decode)rx   rE   rE   rF   rc   s  s    zBase64Engine.charmapc             C   s   t  | t  s( t d t |  f   t t |  d  \ } } t r^ t t |   } n t d d   | D  } |  j	 | | |  } t
 t |  j |   } | S)zencode bytes to base64 string.

        :arg source: byte string to encode.
        :returns: byte string containing encoded data.
        zsource must be bytes, not %srJ   c             s   s   |  ] } t  |  Vq d  S)N)r;   )re   elemrE   rE   rF   rh     s    z,Base64Engine.encode_bytes.<locals>.<genexpr>)r5   r6   rQ   typedivmodr7   r   r   iterrs   r   r   rm   )rx   rA   chunkstail
next_valuegenoutrE   rE   rF   encode_bytes{  s    zBase64Engine.encode_bytesc             c   s   d } xq | | k  ry |   } |   } |   } | d @V| d @d >| d ?BV| d @d >| d ?BV| d ?V| d 7} q	 W| r |   } | d k r | d @V| d ?VnB | d k s t   |   } | d @V| d @d >| d ?BV| d ?Vd	 S)
z>helper used by encode_bytes() to handle little-endian encodingr   ?      rK      rJ      r3   N)r8   )rx   r   r   r   rf   v1v2v3rE   rE   rF   rv     s(    									z!Base64Engine._encode_bytes_littlec             c   s   d } xq | | k  ry |   } |   } |   } | d ?V| d @d >| d ?BV| d @d >| d ?BV| d @V| d 7} q	 W| r |   } | d k r | d ?V| d @d >VnF | d k s t   |   } | d ?V| d @d >| d ?BV| d @d >Vd	 S)
z;helper used by encode_bytes() to handle big-endian encodingr   rK   rJ   r   r   r   r   r3   N)r8   )rx   r   r   r   rf   r   r   r   rE   rE   rF   rr     s(    									zBase64Engine._encode_bytes_bigc             C   s   t  | t  s( t d t |  f   t t |  d  \ } } | d k r[ t d   t t |  j	 |   } y t
 |  j | | |   SWn? t k
 r } z t d | j d f   WYd d } ~ Xn Xd S)zdecode bytes from base64 string.

        :arg source: byte string to decode.
        :returns: byte string containing decoded data.
        zsource must be bytes, not %sr   r3   z(input string length cannot be == 1 mod 4zinvalid character: %rr   N)r5   r6   rQ   r}   r~   r7   rM   r   r   rp   r   ru   KeyErrorargs)rx   rA   r   r   r   rS   rE   rE   rF   decode_bytes  s    zBase64Engine.decode_bytesc       	      c   s   d } xu | | k  r} |   } |   } |   } |   } | | d @d >BV| d ?| d @d >BV| d ?| d >BV| d 7} q	 W| r |   } |   } | | d @d >BV| d k r |   } | d ?| d @d >BVd S)	z>helper used by decode_bytes() to handle little-endian encodingr   rJ   r   rK   r   r   r3   NrE   )	rx   r   r   r   rf   r   r   r   v4rE   rE   rF   rw     s"    							z!Base64Engine._decode_bytes_littlec       	      c   s   d } xu | | k  r} |   } |   } |   } |   } | d >| d ?BV| d @d >| d ?BV| d @d >| BV| d 7} q	 W| r |   } |   } | d >| d ?BV| d k r |   } | d @d >| d ?BVd S)	z;helper used by decode_bytes() to handle big-endian encodingr   rK   r   r   rJ   r   r3   NrE   )	rx   r   r   r   rf   r   r   r   r   rE   rE   rF   rt     s"    							zBase64Engine._decode_bytes_bigc                s[   t    f d d   t |  j  D  } | j   f d d   t |  j  D  t |  S)z2helper to generate set of valid last chars & bytesc             3   s%   |  ] \ } } |   @s | Vq d  S)NrE   )re   ic)bitsrE   rF   rh   G  s    z-Base64Engine.__make_padset.<locals>.<genexpr>c             3   s%   |  ] \ } } |   @s | Vq d  S)NrE   )re   r   r   )r   rE   rF   rh   H  s    )rj   ro   rk   updaterc   	frozenset)rx   r   ZpsetrE   )r   rF   Z__make_padsetE  s    ()zBase64Engine.__make_padsetc             C   s)   |  j  r d n d } | |  j |  f S)zDmask to clear padding bits, and valid last bytes (for strings 2 % 4)r   rK   <   )rq   _Base64Engine__make_padset)rx   r   rE   rE   rF   	_padinfo2K  s    zBase64Engine._padinfo2c             C   s)   |  j  r d n d } | |  j |  f S)zDmask to clear padding bits, and valid last bytes (for strings 3 % 4)rJ   r   0   )rq   r   )rx   r   rE   rE   rF   	_padinfo3R  s    zBase64Engine._padinfo3c             C   s3  t  |  d @} | d k r. |  j \ } } n: | d k rL |  j \ } } n | s\ d | f St d   | d	 } | | k r d | f St | t  r |  j } | | j |  | @} | | k st d   nI |  j	 |  j
 |  | @ } | | k st d   t rt | g  } d | d d
  | f S)a  helper to detect & clear invalid unused bits in last character.

        :arg source:
            encoded data (as ascii bytes or unicode).

        :returns:
            `(True, result)` if the string was repaired,
            `(False, source)` if the string was ok as-is.
        rJ   rK   Fzsource length must != 1 mod 4r3   z%failed to generate valid padding charTNr   )r7   r   r   rM   r5   r   rc   indexr8   rm   rp   r   r6   )rx   rA   r   maskZpadsetlastcmrE   rE   rF   check_repair_unusedY  s(    


	z Base64Engine.check_repair_unusedc             C   s   |  j  |  d S)Nr3   )r   )rx   rA   rE   rE   rF   repair_unused  s    zBase64Engine.repair_unusedc                sT   t    t  s( t d t    f   t   f d d   | D  } |  j |  S)z>encode byte string, first transposing source using offset listzsource must be bytes, not %sc             3   s   |  ] }   | Vq d  S)NrE   )re   rR   )rA   rE   rF   rh     s    z7Base64Engine.encode_transposed_bytes.<locals>.<genexpr>)r5   r6   rQ   r}   r   r   )rx   rA   offsetstmprE   )rA   rF   encode_transposed_bytes  s    z$Base64Engine.encode_transposed_bytesc             C   sV   |  j  |  } d g t |  } x' t | |  D] \ } } | | | <q2 Wt |  S)zGdecode byte string, then reverse transposition described by offset listN)r   r7   zipr   )rx   rA   r   r   ZbufrR   charrE   rE   rF   decode_transposed_bytes  s
    z$Base64Engine.decode_transposed_bytesc       	      C   s  t  | t  s( t d t |  f   |  j } | d } | | d } t |  | k ro t d | f   |  j } d } y; x4 | r | n	 t |  D] } | d >| |  } q WWn% t	 k
 r t d | f   Yn X| r| r | | L} n | d | >d M} | S)a  decode base64 string -> integer

        :arg source: base64 string to decode.
        :arg bits: number of bits in resulting integer.

        :raises ValueError:
            * if the string contains invalid base64 characters.
            * if the string is not long enough - it must be at least
              ``int(ceil(bits/6))`` in length.

        :returns:
            a integer in the range ``0 <= n < 2**bits``
        zsource must be bytes, not %sr   zsource must be %d charsr   zinvalid character in string: %rr3   )
r5   r6   rQ   r}   rq   r7   rM   rp   reversedr   )	rx   rA   r   rq   padcharsr{   r   r   rE   rE   rF   _decode_int  s&    		zBase64Engine._decode_intc             C   s   t  | t  s( t d t |  f   t |  d k rF t d   t rV | d } y |  j |  SWn t k
 r t d   Yn Xd S)z(decode single character -> 6 bit integerzsource must be bytes, not %sr3   zsource must be exactly 1 byter   zinvalid characterN)	r5   r6   rQ   r}   r7   rM   r   rp   r   )rx   rA   rE   rE   rF   decode_int6  s    
zBase64Engine.decode_int6c             C   s   t  | t  s( t d t |  f   t |  d k rF t d   |  j } yM |  j r{ | | d  | | d  d >S| | d  | | d  d >SWn t k
 r t d   Yn Xd S)	z'decodes 2 char string -> 12-bit integerzsource must be bytes, not %srK   zsource must be exactly 2 bytesr3   r   r   zinvalid characterN)	r5   r6   rQ   r}   r7   rM   rp   rq   r   )rx   rA   r{   rE   rE   rF   decode_int12  s    		 $zBase64Engine.decode_int12c             C   s	  t  | t  s( t d t |  f   t |  d k rF t d   |  j } y |  j r | | d  | | d  d >| | d  d >| | d	  d
 >S| | d	  | | d  d >| | d  d >| | d  d
 >SWn t k
 rt d   Yn Xd S)z'decodes 4 char string -> 24-bit integerzsource must be bytes, not %sr   zsource must be exactly 4 bytesrJ   rK   r   r3      r      zinvalid characterN)	r5   r6   rQ   r}   r7   rM   rp   rq   r   )rx   rA   r{   rE   rE   rF   decode_int24  s    		DHzBase64Engine.decode_int24c             C   s   |  j  | d  S)z&decode 5 char string -> 30 bit integer   )r   )rx   rA   rE   rE   rF   decode_int30  s    zBase64Engine.decode_int30c             C   s   |  j  | d  S)zdecode 11 char base64 string -> 64-bit integer

        this format is used primarily by des-crypt & variants to encode
        the DES output value used as a checksum.
        rd   )r   )rx   rA   rE   rE   rF   decode_int64  s    zBase64Engine.decode_int64c                s     d k s t  d   | d } | | 7} |  j rY t | d d d  }   | K  n t d | d  } t t |  j   f d d   | D   S)zencode integer into base64 format

        :arg value: non-negative integer to encode
        :arg bits: number of bits to encode

        :returns:
            a string of length ``int(ceil(bits/6.0))``.
        r   zcaller did not sanitize inputr   c             3   s   |  ] }   | ?d  @Vq d S)r   NrE   )re   rR   )rg   rE   rF   rh   "  s    z+Base64Engine._encode_int.<locals>.<genexpr>ii)r8   rq   r   r   r   rm   )rx   rg   r   r   itrrE   )rg   rF   _encode_int  s    	
	zBase64Engine._encode_intc             C   sP   | d k  s | d k r$ t  d   t r? |  j | | d  S|  j |  Sd S)z0encodes 6-bit integer -> single hash64 characterr   r   zvalue out of ranger3   N)rM   r   rk   rm   )rx   rg   rE   rE   rF   encode_int6(  s
    zBase64Engine.encode_int6c             C   sg   | d k  s | d k r$ t  d   | d @| d ?d @g } |  j rQ t |  } t t |  j |   S)z'encodes 12-bit integer -> 2 char stringr   i  zvalue out of ranger   r   )rM   rq   r   r   r   rm   )rx   rg   rawrE   rE   rF   encode_int121  s    	zBase64Engine.encode_int12c             C   s}   | d k  s | d k r$ t  d   | d @| d ?d @| d ?d @| d ?d @g } |  j rg t |  } t t |  j |   S)z'encodes 24-bit integer -> 4 char stringr   i zvalue out of ranger   r   r   r   )rM   rq   r   r   r   rm   )rx   rg   r   rE   rE   rF   encode_int24:  s    	zBase64Engine.encode_int24c             C   s4   | d k  s | d k r$ t  d   |  j | d  S)z&decode 5 char string -> 30 bit integerr   i?zvalue out of ranger   )rM   r   )rx   rg   rE   rE   rF   encode_int30D  s    zBase64Engine.encode_int30c             C   s4   | d k  s | d k r$ t  d   |  j | d  S)zencode 64-bit integer -> 11 char hash64 string

        this format is used primarily by des-crypt & variants to encode
        the DES output value used as a checksum.
        r   l    zvalue out of rangerd   )rM   r   )rx   rg   rE   rE   rF   encode_int64J  s    zBase64Engine.encode_int64)'__name__
__module____qualname____doc__rk   rq   rm   rp   rs   ru   rz   propertyrc   r   rv   rr   r   rw   rt   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rE   rE   rE   rF   r(      sD   ?"'+#*)(		
c                   sF   e  Z d  Z d Z d Z d d   Z   f d d   Z d d   Z   S)	r)   z<Base64Engine which delays initialization until it's accessedNc             O   s   | | f |  _  d  S)N)
_lazy_opts)rx   r   kwdsrE   rE   rF   rz   \  s    zLazyBase64Engine.__init__c                s;   |  j  \ } } t t |   j | |   |  `  t |  _ d  S)N)r   superr)   rz   r(   	__class__)rx   r   r   )r   rE   rF   
_lazy_init_  s    zLazyBase64Engine._lazy_initc             C   s)   | j  d  s |  j   t j |  |  S)N_)
startswithr   object__getattribute__)rx   attrrE   rE   rF   r   e  s    
z!LazyBase64Engine.__getattribute__)r   r   r   r   r   rz   r   r   rE   rE   )r   rF   r)   X  s
   rq   T)Er   Z
__future__r   r   r   base64r   r   r   rb   r   rW   binasciir	   r
   r   rP   logging	getLoggerr   logZpasslibr   passlib.utils.compatr   r   r   r   r   r   r   r   r   r   r   r   passlib.utils.decorr   __all__r   r   r   r   r   r   r!   r    r"   r>   ZB_NULLrX   r9   r4   r#   r&   r'   rH   rO   rN   r$   r%   r`   ra   r   r(   r)   r*   r+   r,   rE   rE   rE   rF   <module>   sn   "R		!	
  ]