def _crypt_password(self, raw_value): scheme = parameters.get_admin("PASSWORD_SCHEME") if type(raw_value) is unicode: raw_value = raw_value.encode("utf-8") if scheme == "crypt": salt = "".join(Random().sample(string.letters + string.digits, 2)) result = crypt.crypt(raw_value, salt) prefix = "{CRYPT}" elif scheme == "md5": obj = hashlib.md5(raw_value) result = obj.hexdigest() prefix = "{MD5}" # The md5crypt scheme is the only supported method that has both: # (a) a salt ("crypt" has this too), # (b) supports passwords lengths of more than 8 characters (all except # "crypt"). elif scheme == "md5crypt": # The salt may vary from 12 to 48 bits. (Using all six bytes here # with a subset of characters means we get only 35 random bits.) salt = "".join(Random().sample(string.letters + string.digits, 6)) result = md5crypt(raw_value, salt) prefix = "" # the result already has $1$ prepended to it to signify what this is elif scheme == "sha256": obj = hashlib.sha256(raw_value) result = base64.b64encode(obj.digest()) prefix = "{SHA256}" else: scheme = "plain" result = raw_value prefix = "{PLAIN}" return "%s%s" % (prefix, result)
def check_password(self, raw_value): m = self.password_expr.match(self.password) if m is None: return False if type(raw_value) is unicode: raw_value = raw_value.encode("utf-8") scheme = (m.group(2) or m.group(3)).lower() val2 = m.group(4) if scheme == u"crypt": val1 = crypt.crypt(raw_value, val2) elif scheme == u"md5": val1 = hashlib.md5(raw_value).hexdigest() elif scheme == u"sha256": val1 = base64.b64encode(hashlib.sha256(raw_value).digest()) elif scheme == u"$1$": # md5crypt salt, hashed = val2.split('$') val1 = md5crypt(raw_value, str(salt)) val2 = self.password # re-add scheme for comparison below else: val1 = raw_value return constant_time_compare(val1, val2)