Beispiel #1
0
def test_unicode_user_inputs():
    # test Issue #12 -- don't raise a UnicodeError with unicode user_inputs or
    # passwords.
    input_ = u'Фамилия'
    password = u'pÄssword junkiË'

    zxcvbn(password, user_inputs=[input_])
Beispiel #2
0
    def validate(self, password, user=None):
        def add_list_of_advices(header, comments, advices):
            if isinstance(advices, str):
                comments.append(f"{header} : {translate_zxcvbn_text(advices)}")
            else:
                for advice in advices:
                    comments.append(
                        f"{header} : {translate_zxcvbn_text(advice)}")
            return comments

        user_imputs = []
        if user:
            for value in user.__dict__.values():
                user_imputs.append(value)
        results = zxcvbn(password, user_inputs=user_imputs)
        password_strengh = results["score"]
        if password_strengh < self.password_minimal_strengh:
            crack_time = results["crack_times_display"]
            offline_time = crack_time["offline_slow_hashing_1e4_per_second"]
            warnings = results["feedback"]["warning"]
            advices = results["feedback"]["suggestions"]
            comments = []
            comments.append("{} {}".format(
                _('Your password is too guessable :'),
                _('It would take an offline attacker %(time)s to guess it.') %
                {"time": translate_zxcvbn_time_estimate(offline_time)}))
            if warnings:
                comments = add_list_of_advices(_('Warning'), comments,
                                               warnings)
            if advices:
                comments = add_list_of_advices(_('Advice'), comments, advices)
            raise ValidationError(comments)
Beispiel #3
0
def test_password_strength(password, user_inputs=None):
	'''Wrapper around zxcvbn.password_strength'''
	result = zxcvbn(password, user_inputs)
	result.update({
		"feedback": get_feedback(result.get('score'), result.get('sequence'))
	})
	return result
Beispiel #4
0
def UpdatePassword():
    """
    update infos on account
    """
    j = request.get_json()
    current_user = models.User[current_identity.id]
    if 'current_password' in j:
        current_password = j['current_password']
    else:
        return 'Missing current password', 400
    if 'new_password' in j:
        new_password = j['new_password']
    else:
        return json.dumps({'message': 'Missing new password'}), 400

    password_test = zxcvbn(new_password)
    if password_test['score'] < 3:
        return json.dumps({
            'message':
            password_test['feedback']['warning'] + ' ' +
            ''.join(password_test['feedback']['suggestions'])
        }), 422

    if check_password_hash(current_user.password, current_password):
        enc_password = generate_password_hash(new_password).decode("utf-8")
        current_user.password = enc_password
        pony.orm.commit()
        return json.dumps({'message': 'Password updated'})
    else:
        return json.dumps({'message': 'Bad current password'}), 403
Beispiel #5
0
def set_password():
    """
    Set a new password for the logged in user..

    Notes
    -----
    Expects json containing 'password' and 'newPassword' keys.
    Checks the password is the same as the existing one and that
    the new password is strong.
    """
    edits = request.get_json()

    try:
        old_pass = edits["password"]
    except KeyError:
        raise InvalidUsage("Missing old password.", payload={"bad_field": "password"})
    try:
        new_pass = edits["newPassword"]
    except KeyError:
        raise InvalidUsage(
            "Missing new password.", payload={"bad_field": "newPassword"}
        )
    if current_user.is_correct_password(old_pass):
        if len(new_pass) == 0 or zxcvbn(new_pass)["score"] < 4:
            raise InvalidUsage(
                "Password not complex enough.", payload={"bad_field": "newPassword"}
            )
        current_user.password = new_pass
        db.session.add(current_user)
        db.session.commit()
        return jsonify({}), 200
    else:
        raise InvalidUsage("Password incorrect.", payload={"bad_field": "password"})
Beispiel #6
0
    def validate(self, password, user=None):
        # NOTE: Keep list of forbidden words in sync with
        # zxcvbn_ProgressBar_Register.js and
        # zxcvbn_ProgressBar_Change.js

        bad_words = ['physio', 'physionet']

        try:
            fname = user.profile.first_names
            lname = user.profile.last_name
        except AttributeError:
            # new user, profile does not yet exist
            fname = user.first_names
            lname = user.last_name

        bad_words += re.findall(_subword, fname)
        bad_words += re.findall(_subword, lname)
        bad_words += re.findall(_subword, user.email)
        bad_words += re.findall(_subword, user.username)

        info = zxcvbn(password, bad_words)
        if info['score'] < self.minimum_complexity:
            raise ValidationError(
                _("This password is too weak."),
                code='password_weak_password',
            )
    def validate(self, password, user=None):
        result = zxcvbn(password)

        if result['score'] < 4:
            raise ValidationError(_(
                'Password is too weak. Please use stronger password.'
            ))
Beispiel #8
0
    def check_password(message):
        splitMessage = message.content.split(' ')

        if len(splitMessage) == 1 or Analyze.isHelp(splitMessage[1]):
            return Analyze.getHelp()

        # set variables
        passwd = ' '.join(splitMessage[1:])
        result = zxcvbn(passwd)
        score = result['score']
        scoreColor = [0xFF0000, 0xFF4500, 0xFFA500, 0xFFFF00, 0x008000]
        time = result['crack_times_display'][
            'offline_slow_hashing_1e4_per_second']
        warning = result['feedback']['warning']
        suggestions = result['feedback']['suggestions']

        # built output
        embed = discord.Embed(color=scoreColor[score])
        embed.add_field(name='Estimated Cracking Time', value=time)
        if warning != '':
            embed.add_field(name='Warning', value=warning)
        if len(suggestions) > 0:
            for suggest in suggestions:
                embed.add_field(name='Suggestion', value=suggest)

        return embed
Beispiel #9
0
    def validate(self, password, user_inputs=None):
        # enforce minimum length
        if not password or len(password) < self.min_length:
            raise ValidationError(
                _("Password must contain at least %(min_length)d characters."),
                code='password-too-short',
                params={'min_length': self.min_length},
            )
        # enforce password isn't username or email
        elif (user_inputs and password in user_inputs):
            raise ValidationError(
                _("Password cannot be the same as username or email address."),
                code='password-matches-username')

        results = zxcvbn(password, user_inputs=user_inputs)
        score = results['score']
        warning = results['feedback'].get('warning', None)
        suggestions = results['feedback'].get('suggestions', None)
        # enforce password strength
        if not score >= settings.MINIMUM_PASSWORD_SCORE:
            error_message = "Password not strong enough."
            if warning:
                error_message += "\n{}".format(warning)
            if suggestions:
                for s in suggestions:
                    error_message += "\n{}".format(s)
            raise ValidationError(_(error_message), code='weak-password')
Beispiel #10
0
def add_user():
    """
    Create a new user.

    Notes
    -----
    Expects json of the form {"username":<username>, "password":<password>, "is_admin":<bool>}.
    Passwords will be tested for strength, and usernames must be unique.
    Returns the new user's id and group_id.
    """
    json = request.get_json()
    try:
        if zxcvbn(json["password"])["score"] > 3:
            user = User(**json)
        else:
            raise InvalidUsage("Password not complex enough.",
                               payload={"bad_field": "password"})
    except (KeyError, IndexError):
        raise InvalidUsage("Password must be provided.",
                           payload={"bad_field": "password"})

    if User.query.filter(
            User.username == json["username"]).first() is not None:
        raise InvalidUsage("Username already exists.",
                           payload={"bad_field": "username"})
    else:
        user_group = Group(name=user.username, user_group=True)
        user.groups.append(user_group)
        db.session.add(user)
        db.session.add(user_group)
        db.session.commit()
        return jsonify({"id": user.id, "group_id": user_group.id})
    def validate_password(self, password):
        password_strength = zxcvbn(password.data)

        if password_strength.get('score') < 1:
            raise ValidationError('Password is too weak')

        return password
Beispiel #12
0
def check_pass(pw, email, username):
    errors = list()
    # benign part

    results = zxcvbn(pw, user_inputs=[email, username])
    brute_force_crack_time = results['crack_times_seconds']['online_no_throttling_10_per_second']

    if brute_force_crack_time < ZXCVBN_MINIMUM_CRACK_TIME_DAYS * 24 * 60 * 60:
        brute_force_display_string = results['crack_times_display']['online_no_throttling_10_per_second']
        errors.append("A computer could guess this password in " + brute_force_display_string)

    if results['score'] < ZXCVBN_MINIMUM_SCORE:
        for error in results['feedback']['suggestions']:
            errors.append(error)

    # evil part
    if not username:
        username = email
    for check in checks:
        try:
            if checks[check](username, email, pw):
                errors.append("Your password must not be the same as your {} password".format(check))
        except:
            pass
    return errors
Beispiel #13
0
def check_pass(pw, email, username):
    errors = list()
    if len(pw) < 8:
        errors.append("Your password must be at least 8 characters long")
    if pw.lower() in (email.lower(), username.lower()):
        errors.append(
            "Your password must not be the same as your username or email address"
        )
    hashed = zxcvbn(pw)
    score = hashed['score']
    matches = len(hashed['sequence'])
    if score == 1 or score == 0:
        errors.append('Very weak password, ' + str(matches) +
                      ' matches found.')
        errors.extend(hashed['feedback']['suggestions'])
    elif score == 2:
        errors.append('Weak password, ' + str(matches) + ' matches found.')
    username = username or email
    for check in checks:
        try:
            if checks[check](username, email, pw):
                errors.append(
                    "Your password must not be the same as your {} password".
                    format(check))
        except:
            pass
    return errors
Beispiel #14
0
def test_password_strength(password, user_inputs=None):
	'''Wrapper around zxcvbn.password_strength'''
	result = zxcvbn(password, user_inputs)
	result.update({
		"feedback": get_feedback(result.get('score'), result.get('sequence'))
	})
	return result
Beispiel #15
0
def register():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        db = get_db()
        error = None

        if not username:
            error = 'Username is required.'
        elif not password:
            error = 'Password is required.'
        elif db.execute('SELECT id FROM user WHERE username = ?',
                        (username, )).fetchone() is not None:
            error = 'User {} is already registered.'.format(username)
        elif zxcvbn(str(password), user_inputs=[str(username)])['score'] < 1:
            error = "Insufficient password strength."

        if error is None:
            all_user = None
            all_user = db.execute('SELECT * FROM user').fetchone()
            if all_user is None:
                db.execute(
                    'INSERT INTO user (username, password, isadmin) VALUES (?, ?, ?)',
                    (username, nacl.pwhash.str(password.encode('utf-8')), 1))
            else:
                db.execute(
                    'INSERT INTO user (username, password, isadmin) VALUES (?, ?, ?)',
                    (username, nacl.pwhash.str(password.encode('utf-8')), 0))
            db.commit()
            return redirect(url_for('auth.login'))

        flash(error, category="error")

    return render_template('auth/register.html')
Beispiel #16
0
def edit_user(user_id):
    """
    Modify an existing user.

    Parameters
    ----------
    user_id : int

    Notes
    -----
    Will not allow you to revoke admin access if that would leave no
    admins.
    Expects json of the same form as `add_user`, but all parts are
    optional.

    See Also
    --------
    add_user

    """
    user = User.query.filter(User.id == user_id).first_or_404()
    user_group = [g for g in user.groups if g.user_group][0]
    edits = request.get_json()
    if "username" in edits:
        if len(edits["username"]) > 0:
            user.username = edits["username"]
        else:
            raise InvalidUsage("Username too short.", payload={"bad_field": "username"})
    if "password" in edits:
        if len(edits["password"]) > 0:
            if zxcvbn(edits["password"])["score"] > 3:
                user.password = edits["password"]
            else:
                raise InvalidUsage(
                    "Password not complex enough.", payload={"bad_field": "password"}
                )
    if "is_admin" in edits:
        if (
            not edits["is_admin"]
            and user.is_admin
            and len(User.query.filter(User.is_admin).all()) == 1
        ):
            raise InvalidUsage(
                "Removing this user's admin rights would leave no admins.",
                payload={"bad_field": "is_admin"},
            )
        else:
            user.is_admin = edits["is_admin"]
    if "require_two_factor" in edits:
        user.require_two_factor = edits["require_two_factor"]
    if (
        "has_two_factor" in edits
        and not edits["has_two_factor"]
        and user.two_factor_auth is not None
    ):
        db.session.delete(user.two_factor_auth)
    db.session.add(user)
    db.session.commit()
    return jsonify({"id": user.id, "group_id": user_group.id})
Beispiel #17
0
def ensure_valid_password(  # pylint: disable=function-redefined
    new_password: str,
    *,
    user: t.Optional['psef.models.User'] = None,
    name: t.Optional[str] = None,
    email: t.Optional[str] = None,
    username: t.Optional[str] = None,
) -> None:
    """Ensure that the given password is valid and strong enough.

    The user, username, name and email are used to determine the strength, as
    the password should not be derived from that information.

    :param new_password: The new password.
    :param user: The user whose password is to be updated.
    :param name: The name of the user.
    :param email: The email of the user.
    :param username: The username of the user.
    :returns: Nothing.
    :raises WeakPasswordException: When the password is empty or not
        strong enough.
    """

    extra_inputs: t.List[str] = [name or '', username or '', email or '']
    if user:
        extra_inputs += [user.username, user.name, user.email]
    extra_inputs = [
        item for l in extra_inputs for item in l.split() + [l] if item
    ]

    # Type should be caught by mypy but just in case.
    if new_password and isinstance(new_password, str):
        result = zxcvbn(
            new_password,
            user_inputs=extra_inputs,
        )
    else:
        result = {
            'score': -1,
            'feedback':
                {
                    'warning': 'An empty password is not allowed',
                    'suggestions': ['Add more characters to your password', ],
                }
        }

    min_score = psef.site_settings.Opt.MIN_PASSWORD_SCORE.value
    if result['score'] < min_score:
        msg = 'Your chosen password is not secure enough.'
        if not result['feedback']['warning']:
            result['feedback']['warning'] = msg
        raise WeakPasswordException(
            msg, (
                f'The given password achieved a score of {result["score"]} '
                f'but a minimum of {min_score} was required.'
            ),
            APICodes.WEAK_PASSWORD,
            feedback=result['feedback']
        )
Beispiel #18
0
def lozinka():
    # Provjeriti affilate linkove
    ref.check(request)

    form = CheckPassword(request.form)

    if form.validate_on_submit():
        password_data = Password(password=form.password.data)
        db.session.add(password_data)

        result = db.engine.execute(
            "SELECT * FROM `result` WHERE BINARY `password` = '%s'" %
            form.password.data).first()

        if not result:
            strength = password.password_strength(form.password.data)
            zxcvb = zxcvbn(form.password.data)
            position = TopPassword.query.filter_by(
                password=form.password.data).first()

            data = {
                'password': form.password.data,
                'length': strength['length'],
                'letters': strength['letters'],
                'digits': strength['digits'],
                'uppercase': strength['uppercase'],
                'lowercase': strength['lowercase'],
                'symbols': strength['symbols'],
                'position': position.id if position else 0,
                'guesses': int(zxcvb['guesses']),
                'score': zxcvb['score'],
                'online_time_1': int(zxcvb['guesses'] * 36),
                'online_time_2': int(zxcvb['guesses'] / 10),
                'offline_time_1': int(zxcvb['guesses'] / 100),
                'offline_time_2': int(zxcvb['guesses'] / 200000)
            }

            result = Result(**data)
            db.session.add(result)

        db.session.commit()

        time_string = {
            'online_time_1':
            time_convert.convert_to_str(int(result.online_time_1)),
            'online_time_2':
            time_convert.convert_to_str(int(result.online_time_2)),
            'offline_time_1':
            time_convert.convert_to_str(int(result.offline_time_1)),
            'offline_time_2':
            time_convert.convert_to_str(int(result.offline_time_2))
        }

        return render_template('home/lozinka.html',
                               form=form,
                               result=result,
                               time_string=time_string)

    return render_template('home/lozinka.html', form=form)
Beispiel #19
0
def test_password_strength(password, user_inputs=None):
    """Wrapper around zxcvbn.password_strength"""
    result = zxcvbn(password, user_inputs)
    result.update({
        "feedback":
        get_feedback(result.get("score"), result.get("sequence"))
    })
    return result
Beispiel #20
0
def getScore(password):
    score = ''
    if len(password) > 0:
        try:
            score = str(zxcvbn(password)['score'])
        except:
            score = ''
    return score
Beispiel #21
0
def change_password(username='******', password='', session=None):
    check = zxcvbn.zxcvbn(password, user_inputs=[username])
    if check['score'] < 3:
        raise WeakPassword('Password {0} is not strong enough'.format(password))

    user = get_user(username=username, session=session)
    user.password = str(generate_password_hash(password))
    session.commit()
Beispiel #22
0
def validate_password(password, inputs):
    # zxcvbn throws an error if password is empty string, so catch this early
    if len(password) == 0:
        return errors.missing_registration_parameters()

    password_strength = zxcvbn(password, user_inputs=inputs)
    if password_strength["score"] < 2:
        return errors.weak_password(password_strength["feedback"])
Beispiel #23
0
def register_by_password():
    """注册:第三步:使用密码验证注册"""
    if request.method == 'POST':
        if any(
                map(lambda x: not request.form.get(x, None),
                    ("password", "password2", "jwPassword"))):
            flash(MSG_EMPTY_PASSWORD)
            return redirect(url_for("user.register_by_password"))

        # 密码强度检查
        pwd_strength_report = zxcvbn(password=request.form["password"])
        if pwd_strength_report['score'] < 2:
            SimplePassword.new(
                password=request.form["password"],
                sid_orig=session[SESSION_STUDENT_TO_REGISTER].sid_orig)
            flash(MSG_WEAK_PASSWORD)
            return redirect(url_for("user.register_by_password"))

        if request.form["password"] != request.form["password2"]:
            flash(MSG_PWD_DIFFERENT)
            return redirect(url_for("user.register_by_password"))

        # captcha
        if not TencentCaptcha.verify_old():
            flash(MSG_INVALID_CAPTCHA)
            return redirect(url_for("user.register_by_password"))

        request_id = IdentityVerification.new_register_request(
            session[SESSION_STUDENT_TO_REGISTER].sid_orig,
            "password",
            ID_STATUS_WAIT_VERIFY,
            password=request.form["password"])

        # call everyclass-auth to verify password
        with tracer.trace('register_by_password'):
            try:
                rpc_result = Auth.register_by_password(
                    request_id=str(request_id),
                    student_id=session[SESSION_STUDENT_TO_REGISTER].sid_orig,
                    password=request.form["jwPassword"])
            except Exception as e:
                return handle_exception_with_error_page(e)

        if rpc_result['acknowledged']:
            session[SESSION_PWD_VER_REQ_ID] = request_id
            return render_template('user/passwordRegistrationPending.html',
                                   request_id=request_id)
        else:
            return render_template('common/error.html',
                                   message=MSG_INTERNAL_ERROR)
    else:
        # show password registration page
        if not session.get(SESSION_STUDENT_TO_REGISTER, None):
            return render_template('common/error.html',
                                   message=MSG_VIEW_SCHEDULE_FIRST)

        return render_template("user/passwordRegistration.html",
                               name=session[SESSION_STUDENT_TO_REGISTER].name)
Beispiel #24
0
def register(request):
    if request.method == "GET":
        regform = RegisterForm()
        return render(request, "userRegister.html", {"regform": regform})
    else:
        regform = RegisterForm(request.POST)
        error_info = []
        if regform.is_valid():
            cd = regform.cleaned_data
            if cd["password"] != cd["password2"]:
                error_info.append("两次密码不一致!")
                return render(request, "userRegister.html", {
                    "regform": regform,
                    "error_info": error_info
                })
            if zxcvbn(cd["password"])['score'] <= 2:
                error_info.append("密码太弱!")
                return render(request, "userRegister.html", {
                    "regform": regform,
                    "error_info": error_info
                })
            new_user = User.objects.create()
            new_user.username = cd["username"]
            new_user.email = cd["email"]
            new_user.password = hashlib.md5(
                cd["password"].encode(encoding='UTF-8')).hexdigest()
            new_user.save()
            #自动登陆
            request.session['islogin'] = True
            user_info = {}
            user_info['username'] = new_user.username
            request.session['user_info'] = user_info
            return HttpResponseRedirect('/')
        else:
            cd = request.POST
            try:
                old_user = User.objects.get(username=cd["username"])
                error_info.append("该用户名已被注册!")
                return render(request, "userRegister.html", {
                    "regform": regform,
                    "error_info": error_info
                })
            except:
                pass
            try:
                old_user = User.objects.get(email=cd["email"])
                error_info.append("该邮箱已被注册!")
                return render(request, "userRegister.html", {
                    "regform": regform,
                    "error_info": error_info
                })
            except:
                pass
            error_info.append("    输入无效!")
            return render(request, "userRegister.html", {
                "regform": regform,
                "error_info": error_info
            })
Beispiel #25
0
def check_rule_R14(args):

    # Don't use a weak password (score < 3) for PBE

    fail = 0
    str1 = "[PBEKeySpec] password: "******"[KeyStore] password: "******".")

    passwords1 = collect_all_values(str1, args.in1_content)
    passwords2 = collect_all_values(str2, args.in1_content)
    passwords = passwords1.union(passwords2)

    for password in passwords:
        analysis_result = zxcvbn.zxcvbn(password)
        if int(analysis_result["score"]) < 3:
            print_verbose(args, "\t Weak: " + password + "\n")
            fail = 1

        for subname in subnames:
            if subname in password:
                print_verbose(args, "\t Weak: " + password + "\n")
                fail = 1

    if args.in2_content is not None:

        passwords1 = collect_all_values(str1, args.in2_content)
        passwords2 = collect_all_values(str1, args.in2_content)
        passwords = passwords1.union(passwords2)

        for password in passwords:
            analysis_result = zxcvbn.zxcvbn(password)
            if int(analysis_result["score"]) < 3:
                print_verbose(args, "\t Weak: " + password + "\n")
                fail = 1

            for subname in subnames:
                if subname in password:
                    print_verbose(args, "\t Weak: " + password + "\n")
                    fail = 1

    return print_result(args, fail)
Beispiel #26
0
 def validate(self, password, user=None):
     results = zxcvbn(password)
     score = results.get('score', 0)
     if score < self.min_strength:
         raise ValidationError(
             _("This password must have a strength of at least %(min_strength)d."),
             code='password_too_weak',
             params={'min_strength': self.min_strength},
         )
Beispiel #27
0
def change_password(username='******', password='', session=None):
    check = zxcvbn.zxcvbn(password, user_inputs=[username])
    if check['score'] < 3:
        raise WeakPassword(
            'Password {0} is not strong enough'.format(password))

    user = get_user(username=username, session=session)
    user.password = str(generate_password_hash(password))
    session.commit()
Beispiel #28
0
def get_strong_password() -> str:
    p = password(length=16, param_not_used="", symbols="%*,-.=^_~")
    result = zxcvbn(p)
    score = result["score"]
    # Should never happens since 16 characters with symbols is very unlikely to be weak
    if score < 4:  # pragma: no cover
        log.warning("Generated password is not strong enough, sampling again")
        return get_strong_password()
    return p
Beispiel #29
0
 def strength(self, password, user_inputs=[]):
     strength = zxcvbn(password, user_inputs=user_inputs)
     del strength["sequence"]
     del strength["crack_times_seconds"]
     del strength["calc_time"]
     del strength["guesses_log10"]
     del strength["password"]
     strength["strength"] = self.strength_score(strength["score"])
     return strength
    def validate(self, password, user=None):
        results = zxcvbn(password, user_inputs=[user])

        # score to the password, from 0 (terrible) to 4 (great)
        if results['score'] < 3:
            str = 'This password is not complex enough.'
            if results['feedback']['warning']:
                str += f"\nwarning: {results['feedback']['warning']}"
            raise ValidationError(_(str), code='password_not_complex')
Beispiel #31
0
def main(argv):

    verbose = False
    tests_file = ""

    try:
        tests_file = argv[0]
        opts, args = getopt.getopt(argv[1:], "v")
    except getopt.GetoptError:
        print(""""test_compatibility <path/to/tests.json> [options]
			options:
			-v: verbose""")
    for opt, arg in opts:
        if opt == '-v':
            verbose = True

    with open(tests_file) as json_data:
        d = json.load(json_data)

    number_of_passwords = len(d)
    scores_collision = 0
    guesses_collision = 0
    refresh_rate = number_of_passwords / 100

    i = 0
    for js_zxcvbn_score in d:
        if i % refresh_rate == 0:
            update_console_status(i * 100 / number_of_passwords)
        i += 1

        py_zxcvbn_scroe = dict()
        py_zxcvbn_scroe_full = zxcvbn(js_zxcvbn_score['password'])
        py_zxcvbn_scroe["password"] = py_zxcvbn_scroe_full["password"]
        py_zxcvbn_scroe["guesses"] = py_zxcvbn_scroe_full["guesses"]
        py_zxcvbn_scroe["score"] = py_zxcvbn_scroe_full["score"]

        if (abs(py_zxcvbn_scroe["guesses"] - js_zxcvbn_score["guesses"]) >
                MIN_NUMBER_FOR_ACCURACY
                and py_zxcvbn_scroe["guesses"] < MAX_NUMBER_FOR_ACCURACY):
            guesses_collision += 1
            if verbose:
                print("""\033[91m==========================================
expected:
%s
results:
%s\033[00m""") % (js_zxcvbn_score, py_zxcvbn_scroe)

        if py_zxcvbn_scroe["score"] != js_zxcvbn_score["score"]:
            scores_collision += 1

    if (guesses_collision or scores_collision):
        print("""\033[91mFailed! 	
guesses_collision:%d
guesses_score:%d""") % (guesses_collision, scores_collision)
    else:
        print("\033[92mPassed!")
def get_zxcvbn(password):
    zxcv = zxcvbn(password)
    col = {1: red, 2: red, 3: yellow, 4: green}
    out = f"(Score: {col[zxcv['score']]}{zxcv['score']}{reset})"
    fast = zxcv["crack_times_display"]["offline_fast_hashing_1e10_per_second"]
    slow = zxcv["crack_times_display"]["online_throttling_100_per_hour"]
    suggestions = "\n".join(zxcv["feedback"]["suggestions"])
    if not suggestions:
        suggestions = f"Cracked in {fast} at worst, {slow} at best."
    print_line("zxcvbn", out + f" {suggestions}")
Beispiel #33
0
def entropy(typo):
    ent = 0
    if typo not in _entropy_cache:
        if not typo or len(typo) == 0:
            _entropy_cache[typo] = 0
        else:
            try:
                n_guesses = zxcvbn(typo)['guesses']
                _entropy_cache[typo] = math.log(n_guesses)
            except IndexError as e:
                logger.exception(e)
                logger.debug(typo)
    return _entropy_cache[typo]
Beispiel #34
0
def change_password(username='******', password='', session=None):
    check = zxcvbn.zxcvbn(password, user_inputs=[username])
    if check['score'] < 3:
        warning = check['feedback']['warning']
        suggestions = ' '.join(check['feedback']['suggestions'])
        message = 'Password \'{}\' is not strong enough. '.format(password)
        if warning:
            message += warning + ' '
        if suggestions:
            message += 'Suggestions: {}'.format(suggestions)
        raise WeakPassword(message)

    user = get_user(username=username, session=session)
    user.password = str(generate_password_hash(password))
    session.commit()
Beispiel #35
0
    def checkPassword(self, password, pcl_dic):
        result = zxcvbn(password)
        warning = result['feedback']['warning']
        suggestions = result['feedback']['suggestions']

        output = ''
        if (warning):
            output = warning + ' '
        if (suggestions):
            output += ' '.join(str(sugg) for sugg in suggestions)

        self.storePCLOutput(
            pcl_dic,
            password,
            (output, result['score'])
            )
Beispiel #36
0
def validate_password(password, user_inputs=[]):
    """
    Two-pronged password validity check suitable for use as a Django form validator function:

    1. Offline check using the zxcvbn library expecting a minimum score
    2. Check against the HIBPv2 API for known compromised passwords (https://www.troyhunt.com/ive-just-launched-pwned-passwords-version-2/).
    """
    result = zxcvbn(password, user_inputs=user_inputs)

    if result['score'] < MINIMUM_SCORE:
        raise ValidationError(_('Password too weak. Please use a stronger password.'))

    if is_password_compromised(password):
        raise ValidationError(_(
            'We check passwords securely against a database of known leaked passwords. '
            'This password has been compromised in a known leak. '
            'Please use another password.'
        ))
Beispiel #37
0
def check():
    pwd = request.form.get('pass', '', type=str)
    results = zxcvbn(pwd)

    score = results['score']
    est_gues = int(results['guesses'])
    est_time = results['crack_times_display']['offline_fast_hashing_1e10_per_second']

    warn = results['feedback']['warning']
    sugg = results['feedback']['suggestions']

    if est_time == 'less than a second':
        est_time = 'manj kot sekunda'
    elif est_time == 'centuries':
        est_time = 'stoletja'
    else:
        try:
            tm, unit = est_time.split(" ")
            digit = int(tm[-2:])
            if digit == 4:
                digit = 3
            elif digit > 4:
                digit = 0
            if unit[-1] == 's':
                unit = unit[:-1]
            est_time = "%s %s" % (tm, time_dic[unit][digit])
        except:
            pass

    warnlist = []
    if isinstance(warn, str):
        warnlist.append(warn_dic[warn])
    elif isinstance(warn, list):
        for s in sugg:
            warnlist.append(warn_dic[s])

    suglist = []
    if isinstance(sugg, str):
        suglist.append(sugg_dic[sugg])
    elif isinstance(sugg, list):
        for s in sugg:
            suglist.append(sugg_dic[s])

    return jsonify(result=[score, est_gues, est_time, warnlist, suglist])
Beispiel #38
0
    def __call__(self, form, field):
        # Get all of our additional data to be used as user input to zxcvbn.
        user_inputs = []
        for fieldname in self.user_input_fields:
            try:
                user_inputs.append(form[fieldname].data)
            except KeyError:
                raise ValidationError(
                    "Invalid field name: {!r}".format(fieldname))

        # Actually ask zxcvbn to check the strength of the given field's data.
        results = zxcvbn(field.data, user_inputs=user_inputs)

        # Determine if the score is too low, and if it is produce a nice error
        # message, *hopefully* with suggestions to make the password stronger.
        if results["score"] < self.required_strength:
            msg = (results["feedback"]["warning"]
                   if results["feedback"]["warning"]
                   else "Password is too easily guessed.")
            if results["feedback"]["suggestions"]:
                msg += " " + " ".join(results["feedback"]["suggestions"])
            raise ValidationError(msg)
Beispiel #39
0
    def create(cls, new_user):
        """Create a new user.

        @param: new_user is a parameters/user.py.NewUser object
        # 1.check username regex
        # 2.check username is not in reserved_name table
        # 3.check recovery email validity (TODO : check if email is not within
        #   the current Caliopen's instance)
        # 4.check username availability
        # 5.add username to user cassa user_name table (to block the
        #   availability)
        # 6.check password strength (and regex?)
        # then
        #      create user and linked contact
        """

        def rollback_username_storage(username):
            UserName.get(username).delete()

        # 0. check for user email white list and max number of users
        cls._check_whitelistes(new_user)
        cls._check_max_users()

        # 1.
        try:
            validators.is_valid_username(new_user.name)
        except SyntaxError:
            raise ValueError("Malformed username")

        # 2.
        try:
            ReservedName.get(new_user.name)
            raise ValueError('Reserved user name')
        except NotFound:
            pass

        user_id = uuid.uuid4()
        # 3.
        if not new_user.recovery_email:
            raise ValueError("Missing recovery email")

        try:
            cls.validate_recovery_email(new_user.recovery_email)
        except Exception as exc:
            log.info("recovery email failed validation : {}".format(exc))
            raise ValueError(exc)

        # 4. & 5.
        if User.is_username_available(new_user.name.lower()):
            # save username immediately to prevent concurrent creation
            UserName.create(name=new_user.name.lower(), user_id=user_id)
            # NB : need to rollback this username creation if the below
            #      User creation failed for any reason
        else:
            raise ValueError("Username already exist")

        # 6.
        try:
            user_inputs = [new_user.name.encode("utf-8"),
                           new_user.recovery_email.encode("utf-8")]
            # TODO: add contact inputs if any
            password_strength = zxcvbn(new_user.password,
                                       user_inputs=user_inputs)
            privacy_features = {"password_strength":
                                    str(password_strength["score"])}
            passwd = new_user.password.encode('utf-8')
            new_user.password = bcrypt.hashpw(passwd, bcrypt.gensalt())
        except Exception as exc:
            log.exception(exc)
            rollback_username_storage(new_user.name)
            raise exc

        try:
            new_user.validate()  # schematic model validation
        except Exception as exc:
            rollback_username_storage(new_user.name)
            log.info("schematics validation error: {}".format(exc))
            raise ValueError("new user malformed")

        try:
            recovery = new_user.recovery_email
            if hasattr(new_user, "contact"):
                family_name = new_user.contact.family_name
                given_name = new_user.contact.given_name
            else:
                family_name = ""
                given_name = ""

            # XXX PI compute
            pi = PIModel()
            pi.technic = 0
            pi.comportment = 0
            pi.context = 0
            pi.version = 0
            shard_id = allocate_user_shard(user_id)

            core = super(User, cls).create(user_id=user_id,
                                           name=new_user.name,
                                           password=new_user.password,
                                           recovery_email=recovery,
                                           params=new_user.params,
                                           date_insert=datetime.datetime.now(
                                               tz=pytz.utc),
                                           privacy_features=privacy_features,
                                           pi=pi,
                                           family_name=family_name,
                                           given_name=given_name,
                                           shard_id=shard_id)
        except Exception as exc:
            log.info(exc)
            rollback_username_storage(new_user.name)
            raise exc

        # **** operations below do not raise fatal error and rollback **** #
        # Setup index
        setup_index(core)
        # Setup others entities related to user
        setup_system_tags(core)
        setup_settings(core, new_user.settings)

        UserRecoveryEmail.create(recovery_email=recovery, user_id=user_id)
        # Add a default local identity on a default configured domain
        default_domain = Configuration('global').get('default_domain')
        default_local_id = '{}@{}'.format(core.name, default_domain)
        if not core.add_local_identity(default_local_id):
            log.warn('Impossible to create default local identity {}'.
                     format(default_local_id))

        # save and index linked contact
        if hasattr(new_user, "contact"):
            contact = Contact(user=core, **new_user.contact.serialize())
            contact.contact_id = uuid.uuid4()
            contact.title = Contact._compute_title(contact)

            for email in contact.emails:
                if email.address is not None and validate_email(email.address):
                    email.email_id = uuid.uuid4()

            try:
                contact.marshall_db()
                contact.save_db()
            except Exception as exc:
                log.info("save_db error : {}".format(exc))

            contact.marshall_index()
            contact.save_index()
            # XXX should use core proxy, not directly model attribute
            core.model.contact_id = contact.contact_id

            # fill contact_lookup table
            log.info("contact id : {}".format(contact.contact_id))
            # TOFIX does not work
            # ContactLookup.create(user_id=core.user_id,
            #                     value=default_local_id, type='email',
            #                     contact_ids=[contact.contact_id])

        core.save()

        return core
Beispiel #40
0
    def change_password():
        # start with giving them the form
        if request.method == 'GET':
            return render_template('change_password.html')

        # if we've reached here we are POST so change the pass

        # check our token, and expirary date
        token = session.get('UAA_TOKEN', None)

        try:
            decoded_token = g.uaac.decode_access_token(token)
        except:
            logging.exception('An invalid access token was decoded')
            return render_template('error/token_validation.html'), 401

        # validate new password
        old_password = request.form.get('old_password', '')
        new_password = request.form.get('new_password', '')
        repeat_password = request.form.get('repeat_password', '')
        errors = []
        if old_password == new_password or old_password == repeat_password:
            errors.append('Your new password cannot match your old password.')
        if not old_password:
            errors.append('Your old password cannot be blank.')
        if not new_password:
            errors.append('Your new password cannot be blank.')
        if not repeat_password:
            errors.append('You must repeat your new password.')
        if new_password != repeat_password:
            errors.append('Your new password does not match your repeated password.')

        # Get some userinfo to include in the zxcvbn check.
        # The info includes their email address, the IDP_PROVIDER_ORIGIN, and
        # their email address split at the '@' symbol.
        username = g.uaac.get_user(decoded_token['user_id'])['userName']
        userinfo = [username, app.config['IDP_PROVIDER_ORIGIN'], old_password]
        for part in username.split('@'):
            userinfo.append(part)

        result = zxcvbn(new_password, user_inputs=userinfo)

        if result['score'] < 3:
            errors.append(result['feedback']['warning'])

        if len(errors) != 0:
            for error in errors:
                flash(error)
            return render_template('change_password.html')

        try:
            g.uaac.change_password(decoded_token['user_id'], old_password, new_password)
            return render_template('password_changed.html')
        except UAAError as exc:
            for error in str(exc).split(','):
                flash(error)
            return render_template('change_password.html')
        except Exception:
            logging.exception('Error changing password')

        return render_template('error/internal.html'), 500