input:b0003v0627p0001e0001-e0,1,2,3,4,k110,111,112,r8,a0,1,m4,lsfw
  #   ˆl–Ým_J	õ2Ž¥ º [¸Û·ò˜´oÂ„d@¿ÁÀ ?÷     """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
"""
#=============================================================================
# imports
#=============================================================================
from __future__ import with_statement, absolute_import
# core
import logging
log = logging.getLogger(__name__)
import re
import types
from warnings import warn
# site
_argon2_cffi = None  # loaded below
_argon2pure = None  # dynamically imported by _load_backend_argon2pure()
# pkg
from passlib import exc
from passlib.crypto.digest import MAX_UINT32
from passlib.utils import to_bytes
from passlib.utils.binary import b64s_encode, b64s_decode
from passlib.utils.compat import u, unicode, bascii_to_str
import passlib.utils.handlers as uh
# local
__all__ = [
    "argon2",
]

#=============================================================================
# import argon2 package (https://pypi.python.org/pypi/argon2_cffi)
#=============================================================================

# import package
try:
    import argon2 as _argon2_cffi
except ImportError:
    _argon2_cffi = None

# get default settings for hasher
_PasswordHasher = getattr(_argon2_cffi, "PasswordHasher", None)
if _PasswordHasher:
    # we have argon2_cffi >= 16.0, use their default hasher settings
    _default_settings = _PasswordHasher()
    _default_version = _argon2_cffi.low_level.ARGON2_VERSION
else:
    # use these as our fallback settings (for no backend, or argon2pure)
    class _default_settings:
        """
        dummy object to use as source of defaults when argon2 mod not present.
        synced w/ argon2 16.1 as of 2016-6-16
        """
        time_cost = 2
        memory_cost = 512
        parallelism = 2
        salt_len = 16
        hash_len = 16
    _default_version = 0x13

#=============================================================================
# handler
#=============================================================================
class _Argon2Common(uh.SubclassBackendMixin, uh.ParallelismMixin,
                    uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum,
                    uh.GenericHandler):
    """
    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.
    """
    #===================================================================
    # class attrs
    #===================================================================

    #------------------------
    # PasswordHash
    #------------------------

    name = "argon2"
    setting_kwds = ("salt",
                    "salt_size",
                    "salt_len",  # 'salt_size' alias for compat w/ argon2 package
                    "rounds",
                    "time_cost",  # 'rounds' alias for compat w/ argon2 package
                    "memory_cost",
                    "parallelism",
                    "digest_size",
                    "hash_len",  # 'digest_size' alias for compat w/ argon2 package
                    )

    # TODO: could support the optional 'data' parameter,
    #       but need to research the uses, what a more descriptive name would be,
    #       and deal w/ fact that argon2_cffi 16.1 doesn't currently support it.
    #       (argon2_pure does though)

    #------------------------
    # GenericHandler
    #------------------------
    iden