Xc @ sdZddlmZddlZddlZejeZy9ddlmZ e j dkruej ddZ nWne k rdZ nXddlZddlZddlmZddlmZyddlmZWne k rdZnXdd lmZdd lmZmZmZmZmZdd lmZm Z m!Z!m"Z"dd l#m$Z$d dddddgZ%dMZ&dOZ'dPdQdRdSdTdUdVdWdXdYdZg Z(iZ)d-Z*d.Z+e,d/Z-e)j.e-_/dd0Z0defd1YZ1ed2ed3DZ2ed4ed3DZ3e,d5Z4dd6Z5ed7j6Z7dd8Zej8j9d9p}d:Z:e"re:d[krdd<l;m<Z<d=Z=d>Z>d;Z?ne:d\kr ddlmZdd@lm@Z@e@dkZAiZBdAZ=d?Z?n8ddBlCmDZEddClmFZFdDZ=dEZ>dFZ?e:e?kr^dZZ ngermdGnde r|dHnddIe?gD]ZGeGreG^qZHdGeHkrdJZIndHeHkrdKZIndZIdS(]slpasslib.crypto.digest -- crytographic helpers used by the password hashes in passlib .. versionadded:: 1.7 i(tdivisionN(t pbkdf2_hmacthashlibs*ignoring pure-python hashlib.pbkdf2_hmac()(tStruct(twarn(texc(t join_bytest to_native_strtjoin_byte_valuestto_bytest SequenceMixin(tiranget int_typestunicode_or_bytes_typestPY3(tmemoized_propertyt lookup_hashtHashInfotnorm_hash_namet compile_hmactpbkdf1Rii i@tmd2tmd5tsha1ssha-1tsha224ssha-224ssha2-224tsha256ssha-256ssha2-256tsha384ssha-384ssha2-384tsha512ssha-512ssha2-512tmd4tshassha-0tsha0tripemdt ripemd160s ripemd-160c C s|}t|ts*t|dd}ntjdd|jj}|jdr|d}|jdr|d }qnd }||}|r|Stj d |}|rT|j d d d \}}}|r||7}n|}|r%|d|7}|r|d7}n||7}n||}|r;|St j d|||n.|}|j dd}t jd|||||fS(sA internal helper used by :func:`lookup_hash` -- normalize arbitrary hash name to hashlib format. if name not recognized, returns dummy record and issues a warning. :arg name: unnormalized name :returns: tuple with 2+ elements: ``(hashlib_name, iana_name|None, ... 0+ aliases)``. sutf-8s hash names[_ /]t-sscram-is-plusicS s%xtD]}||kr|SqWdS(N(t_known_hash_names(tnametrow((s9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pyt check_tablevs  s8(?i)^(?P[a-z]+)-?(?P\d)?-?(?P\d{3,4})?$R#trevtsizet_s0normalizing unrecognized hash name %r => %r / %rs;normalizing unrecognized hash name and format %r => %r / %r(t isinstancetstrRtretsubtstriptlowert startswithtendswithtmatchtgrouptlogtinfotreplacetwarning( R#torigR%tresulttmt iana_nameR&R't hashlib_name((s9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pyt_get_hash_aliases^sB!          c sjd rDd krDyttSWqDtk r@qDXntjydWntk rqn9Xdfd}|_d|_d|_|Sdkrd d l m }|Sd S( s internal helper used by :func:`lookup_hash` -- lookup hash constructor by name :arg name: name (normalized to hashlib format, e.g. ``"sha256"``) :returns: hash constructor, e.g. ``hashlib.sha256()``; or None if hash can't be located. R(tnewt algorithmstc s |S(N((tmsg(R#t new_ssl_hash(s9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pytconstsRsMwrapper for hashlib.new(%r), generated by passlib.crypto.digest.lookup_hash()Ri(R(snewR>N( R/tgetattrRtAttributeErrorR=t ValueErrort__name__t __module__t__doc__tpasslib.crypto._md4RtNone(R#RBR((R#RAs9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pyt_get_hash_consts(        c C st}y ||SWnttfk r+nXt}t|trt|}|d}||krt|d|}|jdkr|S|||<|St |}|dkr_|rt d|St j |q_nt|t r|St|rJ|}t|j}|d}t |}|dkr2q_||krAq_t}nt j|ddt ||}|||<|rx$|D]}|r|||helper to detect if hash is supported by hashlib.pbkdf2_hmac()RhRiiN(t_stdlib_pbkdf2_hmacRJR#RQRERT(Rb((s9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pytsupported_by_hashlib_pbkdf2s N((RFRGRHRJR#R:R]RBR^R_ReRfRgRRkRm(((s9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pyR\s !   cc s|]}|dAVqdS(i\N((t.0tx((s9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pys sicc s|]}|dAVqdS(i6N((RnRo((s9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pys sc  st|}|\}}}t|ts?t|dd}nt|}||krr||j}|}n||kr|d||7}n||jtj||jt j|rfd}nfd}||_ |S(s This function returns an efficient HMAC function, hardcoded with a specific digest & key. It can be used via ``hmac = compile_hmac(digest, key)``. :arg digest: digest name or constructor. :arg key: secret key as :class:`!bytes` or :class:`!unicode` (unicode will be encoded using utf-8). :param multipart: request a multipart constructor instead (see return description). :returns: By default, the returned function has the signature ``hmac(msg) -> digest output``. However, if ``multipart=True``, the returned function has the signature ``hmac() -> update, finalize``, where ``update(msg)`` may be called multiple times, and ``finalize() -> digest_output`` may be repeatedly called at any point to calculate the HMAC digest so far. The returned object will also have a ``digest_info`` attribute, containing a :class:`lookup_hash` instance for the specified digest. This function exists, and has the weird signature it does, in order to squeeze as provide as much efficiency as possible, by omitting much of the setup cost and features of the stdlib :mod:`hmac` module. tparamtkeytc s(fd}j|fS(s)generated by compile_hmac(multipart=True)c s&}|jj|jS(N(tupdateRM(touter(t _outer_copytinner(s9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pytfinalizes (Rs(Rw(t _inner_copyRu(Rvs9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pythmacs c s<}|j|}|j|j|jS(sgenerated by compile_hmac()(RsRM(R@RvRt(RxRu(s9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pyRys    ( RR)tbytesR R`RMt translatet _TRANS_36tcopyt _TRANS_5Ct digest_info( RMRqt multipartRRBR^R_tklenRy((RxRus9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pyRs"       c C s2t|\}}}t|dd}t|dd}t|ts`tj|ddn|dkr{tdn|d kr|}ngt|tstj|dd n@|d krtd n%||krtd ||fn||}x&t|D]} ||j }qW|| S(s;pkcs#5 password-based key derivation v1.5 :arg digest: digest name or constructor. :arg secret: secret to use when generating the key. may be :class:`!bytes` or :class:`unicode` (encoded using UTF-8). :arg salt: salt string to use when generating key. may be :class:`!bytes` or :class:`unicode` (encoded using UTF-8). :param rounds: number of rounds to use to generate key. :arg keylen: number of bytes to generate (if omitted / ``None``, uses digest's native size) :returns: raw :class:`bytes` of generated key .. note:: This algorithm has been deprecated, new code should use PBKDF2. Among other limitations, ``keylen`` cannot be larger than the digest size of the specified hash. Rptsecrettsalttinttroundsisrounds must be at least 1s int or Nonetkeyleniskeylen must be at least 0s'keylength too large for digest: %r > %rN( RR R)R RRURERJR RM( RMRRRRRBR^R_tblockR(((s9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pyRs(      s>Lc st|dd}tddt|}|j}tts`tjddndkr{tdn|d kr|}nBt|tstj|dd n|dkrtd n||d|}|t krt d n|j r!t |j ||S|jrCt|j ||St||t|tfd td|dD| S(spkcs#5 password-based key derivation v2.0 using HMAC + arbitrary digest. :arg digest: digest name or constructor. :arg secret: passphrase to use to generate key. may be :class:`!bytes` or :class:`unicode` (encoded using UTF-8). :arg salt: salt string to use when generating key. may be :class:`!bytes` or :class:`unicode` (encoded using UTF-8). :param rounds: number of rounds to use to generate key. :arg keylen: number of bytes to generate. if omitted / ``None``, will use digest's native output size. :returns: raw bytes of generated key .. versionchanged:: 1.7 This function will use the first available of the following backends: * `fastpbk2 `_ * :func:`hashlib.pbkdf2_hmac` (only available in py2 >= 2.7.8, and py3 >= 3.4) * builtin pure-python backend See :data:`passlib.crypto.digest.PBKDF2_BACKENDS` to determine which backend(s) are in use. RpRRRRisrounds must be at least 1s int or NoneRskeylen must be at least 1skeylen too long for digestc3 s1|]'}t|VqdS(N(t _pack_uint32(Rnti(t calc_blockt keyed_hmacRR(s9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pys sN(R RR^R)R RRURERJt MAX_UINT32t OverflowErrorRkRjR#RmRlRt_get_pbkdf2_looperRR (RMRRRRRR^t block_count((RRRRs9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pyR_s6$          tPASSLIB_PBKDF2_BACKENDtanys from-bytes(tpartialcC s tt|S(N(Rt_pbkdf2_looper(R^((s9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pyRscC shtj}d}|||}x7t|dD]%}||}||||N}q/W|j||S(sk py3-only implementation of pbkdf2 inner loop; uses 'int.from_bytes' + integer XOR tbigi(Rt from_bytesR R (R^RRMRRtBIGtaccumR(((s9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pyRs  tunpack(tsys_bitsc C sy t|SWntk rnXtrH|d@ rH|d?}d|}nX|d@stry|d?}d|}|d7}q|d?}d|}ntd|t|}td |d d jd t|Dd d jdt|D}dj|}x(t|D]}|d||f7}qW|dj|7}t |dd}tdtd|}t} t ||| | d} | t|<| S(s) We want a helper function which performs equivalent of the following:: def helper(keyed_hmac, digest, rounds): accum = digest for _ in irange(rounds - 1): digest = keyed_hmac(digest) accum ^= digest return accum However, no efficient way to implement "bytes ^ bytes" in python. Instead, using approach where we dynamically compile a helper function based on digest size. Instead of a single `accum` var, this helper breaks the digest into a series of integers. It stores these in a series of`accum_` vars, and performs `accum ^= digest` by unpacking digest and perform xor for each "accum_ ^= digest_". this keeps everything in locals, avoiding excessive list creation, encoding or decoding, etc. :param digest_size: digest size to compile for, in bytes. (must be multiple of 4). :return: helper function with call signature outlined above. iis=%dQs=%dQIiis=%dIsunsupported digest size: %dR^t accum_varss, cs s|]}d|VqdS(sacc_%dN((RnR((s9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pys &st digest_varscs s|]}d|VqdS(sdig_%dN((RnR((s9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pys 'ss def helper(keyed_hmac, digest, rounds): '''pbkdf2 loop helper for digest_size={digest_size}''' unpack_digest = struct.unpack {accum_vars} = unpack_digest(digest) for _ in irange(1, rounds): digest = keyed_hmac(digest) {digest_vars} = unpack_digest(digest) s acc_%d ^= dig_%d s% return struct.pack({accum_vars}) s9texecR tstructthelper( t _looper_cacheROt _have_64_bittNotImplementedErrorRtdicttjoinR R\tcompileteval( R^tcounttfmtRttdicttsourceRtcodetgdicttldictR((s9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pyRs@           "    (thexlify(t int_to_bytescC stS(N(R(R^((s9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pyRXscC snt}t||d}x=t|dD]+}||}|t||dN}q,Wt|t|S(Nii(t_hexlifyRR RR`(RRMRRRR(((s9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pyR[s  Rt fastpbkdf2s hashlib-sslsbuiltin-igffffff?IIll(RR(RR(Rssha-1(Rssha-224ssha2-224(Rssha-256ssha2-256(Rssha-384ssha2-384(Rssha-512ssha2-512(smd4smd4(Rssha-0R(RR(R s ripemd-160(sanys from-bytes(sanysunpacks from-bytes(JRHt __future__RRtloggingt getLoggerRFR3RRlRGtdebugRJt ImportErrorR+tosRRtwarningsRRRjtpasslibRt passlib.utilsRRRR R tpasslib.utils.compatR R R Rtpasslib.utils.decorRt__all__Rt MAX_UINT64R"RNR<RKRTRtcleart clear_cacheRRR~R|RRtpackRtenvirontgett_force_backendt functoolsRRRt_builtin_backendRRRtbinasciiRRRtbtPBKDF2_BACKENDStPBKDF2_SPEED_FACTOR(((s9/usr/lib/python2.7/site-packages/passlib/crypto/digest.pyts          ("    @ / i  #o P ? h     f