K@Xc @`sSdZddlmZmZmZmZddlZddlmZm Z ddl m Z m Z ddlZejeZ ddlZddlZddlmZddlmZmZmZmZddlmZmZmZdd lmZd d d d gZ e!ddddddddddZ"dZ#dZ$ddZ&e'e(fZ)e*e+fZ,e*Z-ddZ.de/fdYZ0e!dd d!d"d#d$d%d&Z1d'e0fd(YZ2dddd)Z3d*Z4d+e fd,YZ5e5Z6x(d-j7D]Z8e6j9e8d.e8q Wd/e0fd0YZ:dddd1Z;dS(2u*passlib.pwd -- password generation helpersi(tabsolute_importtdivisiontprint_functiontunicode_literalsN(t defaultdicttMutableMapping(tceiltlog(texc(tPY2tiranget itervaluest int_types(trngt getrandstrt to_unicode(tmemoized_propertyugenwordudefault_charsetsu genphraseudefault_wordsetstunsafei tweakitfairi$tstrongi0tsecurei<cC`s$t|j}||j|dS(u2return remaining classes in object's MRO after clsi(ttypet__mro__tindex(tobjtclstmro((s//usr/lib/python2.7/site-packages/passlib/pwd.pyt _superclasses3scC`syt|}Wntk r)d}nXtt}x|D]}||cd7ZsN( tlent TypeErrortNoneRtinttvaluestsumR R(tsourcetsizetcountstcharR$((s//usr/lib/python2.7/site-packages/passlib/pwd.pyt_self_info_rate9s       cC`s|rtj|t|Stjj|r>t|dS|jd\}}}|srtd|fnt j ||S(u :param asset_path: string containing absolute path to file, or package-relative path using format ``"python.module:relative/file/path"``. :returns: filehandle opened in 'rb' mode (unless encoding explicitly specified) urbu:uKasset path must be absolute file path or use 'pkg.name:sub/path' format: %r( tcodecst getreadert_open_asset_pathtostpathtisabstopent partitiont ValueErrort pkg_resourcestresource_stream(R/tencodingtpackagetseptsubpath((s//usr/lib/python2.7/site-packages/passlib/pwd.pyR-es  usourcec C`slt}t}y||krtSWntk r9t}nXt|tsgtt|t|kr|ry|j|Wqtk rqXntSt}t}x-|D]%}||kr|n|j|qWt |}d}t||krd}ndj d|| D}t||krR|dt||7}nt d||fdS(u helper for generators -- Throws ValueError if source elements aren't unique. Error message will display (abbreviated) repr of the duplicates in a string/list iiu, cs`s!|]}tt|VqdS(N(treprtstr(Rtword((s//usr/lib/python2.7/site-packages/passlib/pwd.pys su, ... plus %d othersu*`%s` cannot contain duplicate elements: %sN( t_ensure_unique_cachetTrueR!tFalset isinstancet _set_typesR tsettaddtsortedtjoinR3( R&tparamtcachethashabletseentdupstelemttrunctdup_repr((s//usr/lib/python2.7/site-packages/passlib/pwd.pyt_ensure_uniques6   -    #  tSequenceGeneratorcB`seZdZd ZdZeZd Zd d d dZe dZ e dZ dZ d dZ dZerdZnRS( uY Base class used by word & phrase generators. These objects take a series of options, corresponding to those of the :func:`generate` function. They act as callables which can be used to generate a password or a list of 1+ passwords. They also expose some read-only informational attributes. Parameters ---------- :param entropy: Optionally specify the amount of entropy the resulting passwords should contain (as measured with respect to the generator itself). This will be used to auto-calculate the required password size. :param length: Optionally specify the length of password to generate, measured as count of whatever symbols the subclass uses (characters or words). Note if ``entropy`` requires a larger minimum length, that will be used instead. :param rng: Optionally provide a custom RNG source to use. Should be an instance of :class:`random.Random`, defaults to :class:`random.SystemRandom`. Attributes ---------- .. autoattribute:: length .. autoattribute:: symbol_count .. autoattribute:: entropy_per_symbol .. autoattribute:: entropy Subclassing ----------- Subclasses must implement the ``.__next__()`` method, and set ``.symbol_count`` before calling base ``__init__`` method. ustrongcK`sT|jdk std|dk s3|dkr|dkrK|j}ntj||}|dkrxtdntt||j }|dks||kr|}qn||_|dkrtdn||_ |dk r||_ n|r:t |t tfkr:tddj|jntt |j|dS(Nusubclass must set .symbol_countiu!`entropy` must be positive numberiu!`length` must be positive integeruUnexpected keyword(s): %su, (t symbol_countR"tAssertionErrortrequested_entropytentropy_aliasestgetR3R#Rtentropy_per_symboltlengthR RROtobjectR!REtkeystsupert__init__(tselftentropyRVR tkwdst min_length((s//usr/lib/python2.7/site-packages/passlib/pwd.pyRZs&         "cC`st|jdS(uZ Average entropy per symbol (assuming all symbols have equal probability) i(RRP(R[((s//usr/lib/python2.7/site-packages/passlib/pwd.pyRUscC`s|j|jS(u+ Effective entropy of generated passwords. This value will always be a multiple of :attr:`entropy_per_symbol`. If entropy is specified in constructor, :attr:`length` will be chosen so so that this value is the smallest multiple >= :attr:`requested_entropy`. (RVRU(R[((s//usr/lib/python2.7/site-packages/passlib/pwd.pyR\s cC`stddS(u;main generation function, should create one password/phraseuimplement in subclassN(tNotImplementedError(R[((s//usr/lib/python2.7/site-packages/passlib/pwd.pyt__next__$scC`sq|dkrt|St|trHgt|D]}t|^q2S|tkrX|Stj|dddS(uN frontend used by genword() / genphrase() to create passwords u, int, or ureturnsN(R"tnextR@R R titerRtExpectedTypeError(R[treturnst_((s//usr/lib/python2.7/site-packages/passlib/pwd.pyt__call__(s  # cC`s|S(N((R[((s//usr/lib/python2.7/site-packages/passlib/pwd.pyt__iter__5scC`s |jS(N(R`(R[((s//usr/lib/python2.7/site-packages/passlib/pwd.pyRa9sN(t__name__t __module__t__doc__R"RVRRR RPRZRRUR\R`RfRgR Ra(((s//usr/lib/python2.7/site-packages/passlib/pwd.pyROs'#  tascii_72uH0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*?/tascii_62u>0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZtascii_50u2234679abcdefghjkmnpqrstuvwxyzACDEFGHJKMNPQRTUVWXYZthexu0123456789abcdeft WordGeneratorcB`sAeZdZdZdZdddZedZdZ RS(u Class which generates passwords by randomly choosing from a string of unique characters. Parameters ---------- :param chars: custom character string to draw from. :param charset: predefined charset to draw from. :param \*\*kwds: all other keywords passed to the :class:`SequenceGenerator` parent class. Attributes ---------- .. autoattribute:: chars .. autoattribute:: charset .. autoattribute:: default_charsets uascii_62cK`s|r|rFtdqFn(|s<|j}|s<tnt|}||_t|dd}t|dd||_tt|j |dS(Nu,`chars` and `charset` are mutually exclusiveRFuchars( R!tcharsetRQtdefault_charsetsRRNtcharsRYRoRZ(R[RrRpR]((s//usr/lib/python2.7/site-packages/passlib/pwd.pyRZys    cC`s t|jS(N(R Rr(R[((s//usr/lib/python2.7/site-packages/passlib/pwd.pyRPscC`st|j|j|jS(N(RR RrRV(R[((s//usr/lib/python2.7/site-packages/passlib/pwd.pyR`sN( RhRiRjRpR"RrRZRRPR`(((s//usr/lib/python2.7/site-packages/passlib/pwd.pyRoWs cK`s"td|d||}||S(u Generate one or more random passwords. This function uses :mod:`random.SystemRandom` to generate one or more passwords using various character sets. The complexity of the password can be specified by size, or by the desired amount of entropy. Usage Example:: >>> # generate a random alphanumeric string with 48 bits of entropy (the default) >>> from passlib import pwd >>> pwd.genword() 'DnBHvDjMK6' >>> # generate a random hexadecimal string with 52 bits of entropy >>> pwd.genword(entropy=52, charset="hex") '310f1a7ac793f' :param entropy: Strength of resulting password, measured in 'guessing entropy' bits. An appropriate **length** value will be calculated based on the requested entropy amount, and the size of the character set. This can be a positive integer, or one of the following preset strings: ``"weak"`` (24), ``"fair"`` (36), ``"strong"`` (48), and ``"secure"`` (56). If neither this or **length** is specified, **entropy** will default to ``"strong"`` (48). :param length: Size of resulting password, measured in characters. If omitted, the size is auto-calculated based on the **entropy** parameter. If both **entropy** and **length** are specified, the stronger value will be used. :param returns: Controls what this function returns: * If ``None`` (the default), this function will generate a single password. * If an integer, this function will return a list containing that many passwords. * If the ``iter`` constant, will return an iterator that yields passwords. :param chars: Optionally specify custom string of characters to use when randomly generating a password. This option cannot be combined with **charset**. :param charset: The predefined character set to draw from (if not specified by **chars**). There are currently four presets available: * ``"ascii_62"`` (the default) -- all digits and ascii upper & lowercase letters. Provides ~5.95 entropy per character. * ``"ascii_50"`` -- subset which excludes visually similar characters (``1IiLl0Oo5S8B``). Provides ~5.64 entropy per character. * ``"ascii_72"`` -- all digits and ascii upper & lowercase letters, as well as some punctuation. Provides ~6.17 entropy per character. * ``"hex"`` -- Lower case hexadecimal. Providers 4 bits of entropy per character. :returns: :class:`!unicode` string containing randomly generated password; or list of 1+ passwords if :samp:`returns={int}` is specified. RVR\(Ro(R\RVRdR]tgen((s//usr/lib/python2.7/site-packages/passlib/pwd.pytgenwordsFcC`s[t|d-}d|D}td|D}WdQXtjdt|||S(u2 load wordset from compressed datafile within package data. file should be utf-8 encoded :param asset_path: string containing absolute path to wordset file, or "python.module:relative/file/path". :returns: tuple of words, as loaded from specified words file. uutf-8cs`s|]}|jVqdS(N(tstrip(RR<((s//usr/lib/python2.7/site-packages/passlib/pwd.pys scs`s|]}|r|VqdS(N((RR<((s//usr/lib/python2.7/site-packages/passlib/pwd.pys sNu!loaded %d-element wordset from %r(R-ttupleRtdebugR (t asset_pathtfhRstwords((s//usr/lib/python2.7/site-packages/passlib/pwd.pyt _load_wordsets t WordsetDictcB`sqeZdZd Zd ZdZdZdZdZ dZ e dZ dZ dZd ZRS( u Special mapping used to store dictionary of wordsets. Different from a regular dict in that some wordsets may be lazy-loaded from an asset path. cO`s/i|_i|_tt|j||dS(N(tpathst_loadedRYR|RZ(R[targsR]((s//usr/lib/python2.7/site-packages/passlib/pwd.pyRZ s  cC`sKy|j|SWntk r"nX|j|}t|}|j|<|S(N(R~tKeyErrorR}R{(R[tkeyR/R((s//usr/lib/python2.7/site-packages/passlib/pwd.pyt __getitem__%s  cC`s||j|scC`s t|jS(N(RbR(R[((s//usr/lib/python2.7/site-packages/passlib/pwd.pyRgDscC`s t|jS(N(R R(R[((s//usr/lib/python2.7/site-packages/passlib/pwd.pyt__len__GscC`s||jkp||jkS(N(R~R}(R[R((s//usr/lib/python2.7/site-packages/passlib/pwd.pyt __contains__KsN(RhRiRjR"R}R~RZRRRRtpropertyRRgRR(((s//usr/lib/python2.7/site-packages/passlib/pwd.pyR|s      u%eff_long eff_short eff_prefixed bip39upasslib:_data/wordsets/%s.txttPhraseGeneratorcB`sJeZdZdZdZdZddddZedZ dZ RS(uclass which generates passphrases by randomly choosing from a list of unique words. :param wordset: wordset to draw from. :param preset: name of preset wordlist to use instead of ``wordset``. :param spaces: whether to insert spaces between words in output (defaults to ``True``). :param \*\*kwds: all other keywords passed to the :class:`SequenceGenerator` parent class. .. autoattribute:: wordset ueff_longu cK`s|dk r*|dk rXtdqXn.|dkrN|j}|sNtnt|}||_t|tst|}nt|dd||_ |dkr|j }nt |dd}||_ t t |j|dS(Nu,`words` and `wordset` are mutually exclusiveRFuwordsusep(R"R!twordsetRQtdefault_wordsetsR@t_sequence_typesRvRNRzR8RRYRRZ(R[RRzR8R]((s//usr/lib/python2.7/site-packages/passlib/pwd.pyRZys"          cC`s t|jS(N(R Rz(R[((s//usr/lib/python2.7/site-packages/passlib/pwd.pyRPsc`s/fdtjD}jj|S(Nc3`s$|]}jjjVqdS(N(R tchoiceRz(RRe(R[(s//usr/lib/python2.7/site-packages/passlib/pwd.pys s(R RVR8RE(R[Rz((R[s//usr/lib/python2.7/site-packages/passlib/pwd.pyR`sN( RhRiRjRR"RzR8RZRRPR`(((s//usr/lib/python2.7/site-packages/passlib/pwd.pyRZs"cK`s"td|d||}||S(umGenerate one or more random password / passphrases. This function uses :mod:`random.SystemRandom` to generate one or more passwords; it can be configured to generate alphanumeric passwords, or full english phrases. The complexity of the password can be specified by size, or by the desired amount of entropy. Usage Example:: >>> # generate random phrase with 48 bits of entropy >>> from passlib import pwd >>> pwd.genphrase() 'gangly robbing salt shove' >>> # generate a random phrase with 52 bits of entropy >>> # using a particular wordset >>> pwd.genword(entropy=52, wordset="bip39") 'wheat dilemma reward rescue diary' :param entropy: Strength of resulting password, measured in 'guessing entropy' bits. An appropriate **length** value will be calculated based on the requested entropy amount, and the size of the word set. This can be a positive integer, or one of the following preset strings: ``"weak"`` (24), ``"fair"`` (36), ``"strong"`` (48), and ``"secure"`` (56). If neither this or **length** is specified, **entropy** will default to ``"strong"`` (48). :param length: Length of resulting password, measured in words. If omitted, the size is auto-calculated based on the **entropy** parameter. If both **entropy** and **length** are specified, the stronger value will be used. :param returns: Controls what this function returns: * If ``None`` (the default), this function will generate a single password. * If an integer, this function will return a list containing that many passwords. * If the ``iter`` builtin, will return an iterator that yields passwords. :param words: Optionally specifies a list/set of words to use when randomly generating a passphrase. This option cannot be combined with **wordset**. :param wordset: The predefined word set to draw from (if not specified by **words**). There are currently four presets available: ``"eff_long"`` (the default) Wordset containing 7776 english words of ~7 letters. Constructed by the EFF, it offers ~12.9 bits of entropy per word. This wordset (and the other ``"eff_"`` wordsets) were `created by the EFF `_ to aid in generating passwords. See their announcement page for more details about the design & properties of these wordsets. ``"eff_short"`` Wordset containing 1296 english words of ~4.5 letters. Constructed by the EFF, it offers ~10.3 bits of entropy per word. ``"eff_prefixed"`` Wordset containing 1296 english words of ~8 letters, selected so that they each have a unique 3-character prefix. Constructed by the EFF, it offers ~10.3 bits of entropy per word. ``"bip39"`` Wordset of 2048 english words of ~5 letters, selected so that they each have a unique 4-character prefix. Published as part of Bitcoin's `BIP 39 `_, this wordset has exactly 11 bits of entropy per word. This list offers words that are typically shorter than ``"eff_long"`` (at the cost of slightly less entropy); and much shorter than ``"eff_prefixed"`` (at the cost of a longer unique prefix). :param sep: Optional separator to use when joining words. Defaults to ``" "`` (a space), but can be an empty string, a hyphen, etc. :returns: :class:`!unicode` string containing randomly generated passphrase; or list of 1+ passphrases if :samp:`returns={int}` is specified. R\RV(R(R\RVRdR]Rs((s//usr/lib/python2.7/site-packages/passlib/pwd.pyt genphrasesa(<Rjt __future__RRRRR+t collectionsRRtmathRRRtloggingt getLoggerRhR4R.tpasslibRtpasslib.utils.compatR R R R t passlib.utilsR RRtpasslib.utils.decorRt__all__tdictRSRR*R"R-tlistRvRRBt frozensetRAR=RNRWRORqRoRtR{R|RtsplittnameRRR(((s//usr/lib/python2.7/site-packages/passlib/pwd.pytsT"    "    ,     . LM #> R