Ejemplo n.º 1
0
	def __init__(self, login, email, password):
		"""Takes a validated username, email, and password, and initializes a User"""
		# Simply save the username and email
		self.login = login
		self.email = email

		# Generate a random salt and compute the password hash using the defaults
		salt = secure_random(SALT_BYTES)
		digest = PASSWORD_ALG(password, salt, PASSWORD_ROUNDS)[:PASSWORD_BYTES]
		# Save the password hash, along with the salt, algorithm, and work factor
		# used to compute it
		self.password = to64(digest)
		self.salt = to64(salt)
		self.algorithm = PASSWORD_ALG.name
		self.work_factor = PASSWORD_ROUNDS
Ejemplo n.º 2
0
	def verify(cls, login, password):
		"""Take a username and password and return the corresponding user, if it exists
		and the provided password is correct"""
		# FIXME: minor timing attack to check if user exists
		# Grab data about the user from the database using their login. Deny
		# the login attempt if the specified user doesn't exist.
		user = cls.get(login)
		if user is None:
			return None

		# Retrieve the algorithm and parameters from the database to determine
		# which hashing function to use. These may not be the same as the current
		# standard, so be sure the correct paramaters are being used to produce
		# the same hash as the one stored in the database.
		stored_pass = from64(user.password)
		stored_dig_len = len(stored_pass)
		stored_salt = from64(user.salt)
		stored_salt_len = len(stored_salt)
		stored_alg = get_algorithm(user.algorithm)
		stored_work = user.work_factor
		presented = stored_alg(password, stored_salt, stored_work)[:stored_dig_len]

		# Make sure the comparison is done using this special operation, to avoid
		# timing attacks. The execution time of the comparison MUST NOT DEPEND ON
		# THE LOCATIONS OF ANY DIFFERENCES. If the credentials presented don't match
		# the database, deny the login attempt.
		if not slow_equals(presented, stored_pass):
			return None

		# If the stored hashing parameters don't match the current standard,
		# update them. Note that THIS MUST ONLY BE DONE ONCE THE PASSWORD HAS
		# BEEN VERIFIED using the stored values, or the account could be updated
		# to use invalid credentials. Which would be very bad.
		if (stored_alg is not PASSWORD_ALG or stored_dig_len != PASSWORD_BYTES or
				stored_salt_len != SALT_BYTES or stored_work != PASSWORD_ROUNDS):
			salt = secure_random(SALT_BYTES)
			stream = PASSWORD_ALG(password, salt, PASSWORD_ROUNDS)
			user.password = to64(stream[:PASSWORD_BYTES])
			user.salt = to64(salt)
			user.algorithm = PASSWORD_ALG.name
			user.work_factor = PASSWORD_ROUNDS

		return user
Ejemplo n.º 3
0
 def pres(cap):
     h2 = h.copy()
     # If passed the null requesting capability, hash the nonce instead
     h2.update(nonce if cap is None else cap.key)
     return to64(h2.digest())