def _adapt_backend_error(cls, err, hash=None, self=None): """ internal helper invoked when backend has hash/verification error; used to adapt to passlib message. """ backend = cls.get_backend() # parse hash to throw error if format was invalid, parameter out of range, etc. if self is None and hash is not None: self = cls.from_string(hash) # check constraints on parsed object # XXX: could move this to __init__, but not needed by needs_update calls if self is not None: self._validate_constraints(self.memory_cost, self.parallelism) # as of cffi 16.1, lacks support in hash_secret(), so genhash() will get here. # as of cffi 16.2, support removed from verify_secret() as well. if backend == "argon2_cffi" and self.data is not None: raise NotImplementedError( "argon2_cffi backend doesn't support the 'data' parameter") # fallback to reporting a malformed hash text = str(err) if text not in ["Decoding failed" # argon2_cffi's default message ]: reason = "%s reported: %s: hash=%r" % (backend, text, hash) else: reason = repr(hash) raise exc.MalformedHashError(cls, reason=reason)
def from_string(cls, hash): # NOTE: assuming hash will be unicode, or use ascii-compatible encoding. # TODO: switch to working w/ str or unicode if isinstance(hash, unicode): hash = hash.encode("utf-8") if not isinstance(hash, bytes): raise exc.ExpectedStringError(hash, "hash") m = cls._hash_regex.match(hash) if not m: raise exc.MalformedHashError(cls) type, version, memory_cost, time_cost, parallelism, keyid, data, salt, digest = \ m.group("type", "version", "memory_cost", "time_cost", "parallelism", "keyid", "data", "salt", "digest") if keyid: raise NotImplementedError("argon2 'keyid' parameter not supported") return cls( type=type.decode("ascii"), version=int(version) if version else 0x10, memory_cost=int(memory_cost), rounds=int(time_cost), parallelism=int(parallelism), salt=b64s_decode(salt) if salt else None, data=b64s_decode(data) if data else None, checksum=b64s_decode(digest) if digest else None, )