def test_safe_str_cmp_no_builtin(): import werkzeug.security as sec prev_value = sec._builtin_safe_str_cmp sec._builtin_safe_str_cmp = None assert safe_str_cmp('a', 'ab') is False assert safe_str_cmp('str', 'str') is True assert safe_str_cmp('str1', 'str2') is False sec._builtin_safe_str_cmp = prev_value
def test_safe_str_cmp_no_builtin(): import werkzeug.security as sec prev_value = sec._builtin_safe_str_cmp sec._builtin_safe_str_cmp = None assert safe_str_cmp("a", "ab") is False assert safe_str_cmp("str", "str") is True assert safe_str_cmp("str1", "str2") is False sec._builtin_safe_str_cmp = prev_value
def upload_dance(): if app.config['RG_VERIFY_ENDPOINT']: user_id, user_token = request.form['user_id'], request.form['user_token'] check_token = hmac.new(app.config['RG_VERIFY_SECRET'], user_id, hashlib.sha1).hexdigest() if not safe_str_cmp(user_token, check_token): abort(403) gif = request.files['moves'] gif_data = gif.read() if gif and check_gif(gif_data): dance_id = hashlib.sha1(gif_data).hexdigest() dance = { '_id': dance_id, 'ts': time.time(), 'ip': request.remote_addr, 'ua': request.user_agent.string, 'status': 'new', } if app.config['RG_VERIFY_ENDPOINT']: dance['rg_id'] = user_id g.db.save(dance) with open(os.path.join(app.config['UPLOAD_FOLDER'], dance_id + '.gif'), 'w') as out: out.write(gif_data) json_data = dance_json(dance) json_data['token'] = dance_owner_token(dance_id) return json.jsonify(json_data)
def check_password_hash(self, password): if PYVER < 3 and isinstance(password, unicode): password = password.encode('u8') elif PYVER >= 3 and isinstance(password, bytes): password = password.decode('utf-8') password = str(password) return safe_str_cmp(bcrypt.hashpw(password, self.password), self.password)
def before_request(): connect_db() if request.method not in ['GET', 'HEAD', 'OPTIONS']: if (not request.headers.get('X-CSRFT') or not session.get('csrft') or not safe_str_cmp(session['csrft'], request.headers['X-CSRFT'])): abort(400) g.is_reviewer = False auth = request.authorization if (auth and request.scheme == 'https' and safe_str_cmp(auth.username, app.config['REVIEWER_USERNAME'])): crypted = bcrypt.hashpw(auth.password, app.config['REVIEWER_PASSWORD']) if safe_str_cmp(crypted, app.config['REVIEWER_PASSWORD']): g.is_reviewer = True
def check_password_hash(self, pw_hash, password): '''Tests a password hash against a candidate password. The candidate password is first hashed and then subsequently compared in constant time to the existing hash. This will either return `True` or `False`. Example usage of :class:`check_password_hash` would look something like this:: pw_hash = bcrypt.generate_password_hash('secret', 10) bcrypt.check_password_hash(pw_hash, 'secret') # returns True :param pw_hash: The hash to be compared against. :param password: The password to compare. ''' # Python 3 unicode strings must be encoded as bytes before hashing. if PY3 and isinstance(pw_hash, bytes): pw_hash = pw_hash.decode('utf-8') if PY3 and isinstance(password, bytes): password = password.decode('utf-8') if not PY3 and isinstance(pw_hash, unicode): pw_hash = pw_hash.encode('utf-8') if not PY3 and isinstance(password, unicode): password = password.encode('utf-8') return safe_str_cmp(bcrypt.hashpw(password, pw_hash), pw_hash)
def add_message(): try: token, uses = session.get('csrf', '').split(':', 1) except: flash('Whoa! Looks like there was a problem', 'error') return redirect(url_for('home')) else: _token = request.form.get('_token', '') _token, uses = _token.split(':', 1) if not safe_str_cmp(token, _token) or not int(uses) <= 10: flash('Looks like there was a problem', 'error') return redirect(url_for('home')) else: session['csrf'] = '{}:{}'.format(token, int(uses) + 1) msg = request.form.get('your-question') if msg is None or '' == msg: flash('Please ask a question', 'warning') return redirect(url_for('home')) count = g.redis.incr('question_counter') if 'messages' not in session: session['messages'] = [count] else: session['messages'].append(count) g.redis.set('message:{}'.format(count), msg) flash('Your question has been asked, just hang out here (or come back ' 'later for your answers') return redirect(url_for('listen'))
def confirm_reset_password_token(token): max_age_key = 'USERS_RESET_PASSWORD_TOKEN_MAX_AGE_IN_SECONDS' max_age = current_app.config[max_age_key] salt = current_app.config['USERS_RESET_PASSWORD_TOKEN_SALT'] serializer = URLSafeTimedSerializer(current_app.config['SECRET_KEY']) user, data = None, None expired, invalid = False, False try: data = serializer.loads( token, max_age=max_age, salt=salt) except SignatureExpired: d, data = serializer.loads_unsafe(token, salt=salt) expired = True except (BadSignature, TypeError, ValueError): invalid = True if data: user = User.get(id=data[0]) if not invalid and user and user.password: password_hash = hashlib.md5(user.password).hexdigest() if not safe_str_cmp(password_hash, data[1]): invalid = True expired = expired and (user is not None) logger.debug("reset password token confirmed?", expired=expired, invalid=invalid, user=user, data=data) return expired, invalid, user, data
def add_response(): try: token, uses = session.get('csrf', '').split(':', 1) except: flash('Whoa! Looks like there was a problem', 'error') return redirect(url_for('home')) else: _token = request.form.get('_token', '') _token, uses = _token.split(':', 1) if not safe_str_cmp(token, _token) or not int(uses) <= 10: flash('Looks like there was a problem', 'error') return redirect(url_for('home')) else: session['csrf'] = '{}:{}'.format(token, int(uses) + 1) qid = request.form.get('question', 0) resp = request.form.get('your-answer', '') if resp is None or '' == resp: flash('Whoa there, enter a response.', 'error') return redirect(url_for('question', id=qid)) resp_count = g.redis.incr('response:{}:count'.format(qid)) g.redis.set('response:{}:{}'.format(qid, resp_count), resp) flash('Your response has been added!') return redirect(url_for('question', id=qid))
def compare_password(hashed_password, password): if safe_str_cmp(bcrypt.hashpw(password.encode('utf-8'), hashed_password.encode('utf-8')), hashed_password): print "It matches" return True else: print "It does not match" return False
def remove_dance(dance_id): token = request.headers.get('X-Owner-Token') if not token or not safe_str_cmp(token, dance_owner_token(dance_id)): abort(403) dance = g.db[dance_id] dance['status'] = 'removed' g.db.save(dance) return '', 200
def is_valid_password(self, password): """ Check if given password is valid. """ return safe_str_cmp( bcrypt.hashpw(password.encode('utf-8'), self.password_hash.encode('utf-8')), self.password_hash )
def bcrypt_check(data, password): import bcrypt try: encoded = data.encode('utf-8') encoded2 = bcrypt.hashpw(password.encode('utf-8'), encoded) except Exception: raise ValueError('Invalid hash format') return safe_str_cmp(encoded, encoded2)
def test_login(username, password): password = password.encode('utf-8') pw_hash = current_app.redis.get('user:'******':password') if not pw_hash: return False if not safe_str_cmp(hashlib.sha1(password).hexdigest(), pw_hash): return False return True
def _token_loader(token): try: data = _security.remember_token_serializer.loads(token) user = _security.datastore.find_user(id=data[0]) if user and safe_str_cmp(md5(user.password), data[1]): return user except: pass return AnonymousUser()
def test_safe_str_cmp(): assert safe_str_cmp("a", "a") is True assert safe_str_cmp(b"a", u"a") is True assert safe_str_cmp("a", "b") is False assert safe_str_cmp(b"aaa", "aa") is False assert safe_str_cmp(b"aaa", "bbb") is False assert safe_str_cmp(b"aaa", u"aaa") is True assert safe_str_cmp(u"aaa", u"aaa") is True
def test_safe_str_cmp(): assert safe_str_cmp('a', 'a') is True assert safe_str_cmp(b'a', u'a') is True assert safe_str_cmp('a', 'b') is False assert safe_str_cmp(b'aaa', 'aa') is False assert safe_str_cmp(b'aaa', 'bbb') is False assert safe_str_cmp(b'aaa', u'aaa') is True assert safe_str_cmp(u'aaa', u'aaa') is True
def scrypt_check(data, password): try: salt, Nexp, r, p, keylen, h = data.split('$') Nexp = int(Nexp, 10) r = int(r, 10) p = int(p, 10) keylen = int(keylen, 10) except Exception: raise ValueError('Invalid hash format') return safe_str_cmp(h, _scrypt_password_hash(password, salt, Nexp, r, p, keylen))
def unserialize(cls, string, secret_key): """Load the secure cookie from a serialized string. :param string: the cookie value to unserialize. :param secret_key: the secret key used to serialize the cookie. :return: a new :class:`SecureCookie`. """ # explicitly convert it into a bytestring because python 2.6 # no longer performs an implicit string conversion on hmac secret_key = str(secret_key) if isinstance(string, unicode): string = string.encode('utf-8', 'replace') try: base64_hash, data = string.split('?', 1) except (ValueError, IndexError): items = () else: items = {} mac = hmac(secret_key, None, cls.hash_method) for item in data.split('&'): mac.update('|' + item) if not '=' in item: items = None break key, value = item.split('=', 1) # try to make the key a string key = url_unquote_plus(key) try: key = str(key) except UnicodeError: pass items[key] = value # no parsing error and the mac looks okay, we can now # sercurely unpickle our cookie. try: client_hash = base64_hash.decode('base64') except Exception: items = client_hash = None if items is not None and safe_str_cmp(client_hash, mac.digest()): try: for key, value in items.iteritems(): items[key] = cls.unquote(value) except UnquoteError: items = () else: if '_expires' in items: if time() > items['_expires']: items = () else: del items['_expires'] else: items = () return cls(items, secret_key, False)
def authenticate(username, password): """ Function that gets called when a user calls the /auth endpoint with their username and password :param username: User's username in string format. :param password: User's un-encrypted password in string format. :return: A user if authentication was successful, None otherwise. """ user = UserModel.find_by_username(username) if user and safe_str_cmp(user.password, password): return user
def authenticate(username, password): """ Checks if the user which is supplied in the /POST request exists :param username: username field in the JSON :param password: password field in the JSON :return: user_id """ username_table = {u.username: u for u in users} user = username_table.get(username, None) if user and safe_str_cmp(user.password.encode('utf-8'), password.encode('utf-8')): return user
def pbkdf2_check(data, password): try: algorithm, iterations, salt, _ = data.split('$', 3) iterations = int(iterations) except Exception: raise ValueError('Invalid hash format') if algorithm != 'pbkdf2_sha256': raise ValueError('Unknown pbkdf2 algorithm variant') data2 = pbkdf2_encode(password, salt, iterations) return safe_str_cmp(data, data2)
def check_csrf_token(): """Checks that token is correct, aborting if not""" if request.method in ("GET",): # not exhaustive list return token = request.form.get("csrf_token") if token is None: app.logger.warning("Expected CSRF Token: not present") abort(400) if not safe_str_cmp(token, csrf_token()): app.logger.warning("CSRF Token incorrect") abort(400)
def unserialize(cls, string, secret_key): """Load the secure cookie from a serialized string. :param string: the cookie value to unserialize. :param secret_key: the secret key used to serialize the cookie. :return: a new :class:`SecureCookie`. """ if isinstance(string, text_type): string = string.encode('utf-8', 'replace') if isinstance(secret_key, text_type): secret_key = secret_key.encode('utf-8', 'replace') try: base64_hash, data = string.split(b'?', 1) except (ValueError, IndexError): items = () else: items = {} mac = hmac(secret_key, None, cls.hash_method) for item in data.split(b'&'): mac.update(b'|' + item) if not b'=' in item: items = None break key, value = item.split(b'=', 1) # try to make the key a string key = url_unquote_plus(key.decode('ascii')) try: key = to_native(key) except UnicodeError: pass items[key] = value # no parsing error and the mac looks okay, we can now # sercurely unpickle our cookie. try: client_hash = base64.b64decode(base64_hash) except TypeError: items = client_hash = None if items is not None and safe_str_cmp(client_hash, mac.digest()): try: for key, value in iteritems(items): items[key] = cls.unquote(value) except UnquoteError: items = () else: if '_expires' in items: if time() > items['_expires']: items = () else: del items['_expires'] else: items = () return cls(items, secret_key, False)
def unserialize(cls, string, secret_key): """Load the secure cookie from a serialized string. :param string: the cookie value to unserialize. :param secret_key: the secret key used to serialize the cookie. :return: a new :class:`SecureCookie`. """ if isinstance(string, unicode): string = string.encode("utf-8", "replace") if isinstance(secret_key, unicode): secret_key = secret_key.encode("utf-8", "replace") try: base64_hash, data = string.split("?", 1) except (ValueError, IndexError): items = () else: items = {} mac = hmac(secret_key, None, cls.hash_method) for item in data.split("&"): mac.update("|" + item) if not "=" in item: items = None break key, value = item.split("=", 1) # try to make the key a string key = url_unquote_plus(key) try: key = str(key) except UnicodeError: pass items[key] = value # no parsing error and the mac looks okay, we can now # sercurely unpickle our cookie. try: client_hash = base64_hash.decode("base64") except Exception: items = client_hash = None if items is not None and safe_str_cmp(client_hash, mac.digest()): try: for key, value in items.iteritems(): items[key] = cls.unquote(value) except UnquoteError: items = () else: if "_expires" in items: if time() > items["_expires"]: items = () else: del items["_expires"] else: items = () return cls(items, secret_key, False)
def multi_constant_time_compare(value, expecteds): """ Compares ``value`` against each of the strings in ``expecteds``, returns ``True`` if it is equal to any of them, and ``False`` otherwise. The amount of time this takes to execute is independent of how similar ``value`` is to the items in ``expecteds``. """ found = 0 for expected in expecteds: found |= safe_str_cmp(value, expected) return bool(found)
def show_settings(): if request.method == "POST": if not g.user.check_password(request.form['old_password']): flash('Invalid current password.', 'error') elif not safe_str_cmp(request.form['new_password'], request.form['new_password_confirm']): flash('New password mismatch. Make sure you type the password correctly on both fields.', 'error') else: g.user.set_password(request.form['new_password']) g.db.commit() flash('Password changed.', 'success') return render_template('settings.html', user=g.user)
def check_password(self, password): """Check the parameter `password` for a match with the user's password""" if self.password.startswith("pbkdf2"): return check_password_hash(self.password, password) else: # handle scuttle passwords (sha1) and migrate if correct rv = safe_str_cmp(self.password, hashlib.sha1(password).hexdigest()) if rv is True: self.set_password(password) db.Session.commit() return rv
def password_login(id_type, identifier, password, pg=utils.postgres): """ Attempts to log in using (`identifier`, `password`) `id_type` must be either 'user_id' or 'email' Returns the user, or raises one of :exc:`ShouldUseRaven`, :exc:`EmailNotFound`, :exc:`BadPassword` or :exc:`UserDisabled`. """ assert id_type in ("user_id", "email") # the schema guarantees us that raven users only have cam emails if id_type == "email": identifier = identifier.lower() if identifier.endswith("@cam.ac.uk"): raise ShouldUseRaven(identifier) query = "SELECT * FROM users WHERE {0} = %s".format(id_type) with pg.cursor(True) as cur: cur.execute(query, (identifier, )) assert cur.rowcount in (0, 1) if cur.rowcount == 1: user = cur.fetchone() else: assert id_type != "user_id" # this shouldn't happen logger.info("password login failed - bad %s %r", id_type, identifier) raise EmailNotFound(identifier) if user["user_type"] == 'raven': logger.warning("password login attempted on raven user %s (%s)", user["crsid"], user["user_id"]) raise ShouldUseRaven(user["email"]) elif user["user_type"] != 'password': logger.warning("password login attempted on non password user %s", user["user_id"]) raise WrongUserType(user["user_type"], 'password') if not user["enable_login"]: logger.warning("password login attempted while disabled - " "user %s", user["user_id"]) raise UserDisabled(user["user_id"]) compare = bcrypt.hashpw(password, user["password_bcrypt"]) if safe_str_cmp(user["password_bcrypt"], compare): logger.info("good password for user %s", user["user_id"]) return user else: logger.info("bad password for user %s", user["user_id"]) raise BadPassword(user["user_id"])
def decode_cookie(cookie): """ decode cookies managed by flask.ext.login """ from router import SECRET_KEY try: payload, digest = cookie.rsplit(u'|', 1) if hasattr(digest, 'decode'): digest = digest.decode('ascii') except ValueError: return if safe_str_cmp(_cookie_digest(payload, SECRET_KEY), digest): return payload
def authenticate(username, password): user = UserModel.find_by_username( username ) # if there is not a username with username will return None if user and safe_str_cmp(user.password, password): return user
def authenticate(self, username, password): user = self.usernameTable.get(username, None) if user and safe_str_cmp(user.password.encode('utf-8'), password.encode('utf-8')): return user
def validate(self): ''' Validates a CSRF token for the current request. If CSRF token is invalid, stops execution and sends a Forbidden error response to the client. Can be used in combination with :class:`exempt` to programmatically enable CSRF protection per request. Example usage of :class:`validate` might look something like:: csrf = SeaSurf(app) @csrf.exempt @app.route('/sometimes_requires_csrf') def sometimes_requires_csrf(): if not oauth_request(): # validate csrf unless this is an OAuth request csrf.validate() return render_template('sometimes_requires_csrf.html') ''' if not has_request_context(): raise Forbidden(description=REASON_NO_REQUEST) # Tell _after_request to still set the CSRF token cookie when this # view was exemp, but validate was called manually in the view g.csrf_validation_checked = True server_csrf_token = session.get(self._csrf_name, None) if request.is_secure and self._check_referer: referer = request.headers.get('Referer') if referer is None: error = (REASON_NO_REFERER, request.path) error = u'Forbidden ({0}): {1}'.format(*error) current_app.logger.warning(error) raise Forbidden(description=REASON_NO_REFERER) # By setting the Access-Control-Allow-Origin header, browsers # will let you send cross-domain AJAX requests so if there is # an Origin header, the browser has already decided that it # trusts this domain otherwise it would have blocked the # request before it got here. allowed_referer = request.headers.get('Origin') or request.url_root if not _same_origin(referer, allowed_referer): error = REASON_BAD_REFERER.format(referer, allowed_referer) description = error error = (error, request.path) error = u'Forbidden ({0}): {1}'.format(*error) current_app.logger.warning(error) raise Forbidden(description=description) request_csrf_token = request.form.get(self._csrf_name, '') if not request_csrf_token: # Check to see if the data is being sent as JSON try: if hasattr(request, 'json') and request.json: request_csrf_token = request.json.get(self._csrf_name, '') # Except Attribute error if JSON data is a list except (BadRequest, AttributeError): pass if not request_csrf_token: # As per the Django middleware, this makes AJAX easier and # PUT and DELETE possible. request_csrf_token = request.headers.get(self._csrf_header_name, '') some_none = None in (request_csrf_token, server_csrf_token) if some_none or not safe_str_cmp(request_csrf_token, server_csrf_token): error = (REASON_BAD_TOKEN, request.path) error = u'Forbidden ({0}): {1}'.format(*error) current_app.logger.warning(error) raise Forbidden(description=REASON_BAD_TOKEN)
def authenticate(email_address, password): user = UserModel.find_by_email_address(email_address) if user and safe_str_cmp(user.password, password): return user
def authenticate(username, password): user = UserRepository.getByUsername(username) if user and safe_str_cmp(user.password, password): return user
def authenticate(username, password): user = User.objects(username=username).first() if user and safe_str_cmp(user.password.encode('utf-8'), password.encode('utf-8')): return user
def authenticate(username: str, password: str) -> dict: user = User.find_by_username(username) if user and safe_str_cmp(user.password, password): return user