示例#1
0
def check1(pw):
    pw_ent_bits = password_strength(pw)['entropy']
    result = get_pos_typos(pw, pw_ent_bits, 290729)
    result.sort(key=lambda x: x[1], reverse=True)
    print "len:{}".format(len(result))
    for (typ, pp) in result:
        print("typo:{}, pp:{}, strength:{}".format(
            typ, pp,
            password_strength(typ)['entropy']))
示例#2
0
    def __call__(self, node, value):
        request = node.bindings.get('request')
        localizer = get_localizer(request)
        settings = request.registry.settings
        value = value.replace(" ", "")
        password_min_entropy = int(settings.get('password_entropy', 60))

        # We accept a 10% of variance in password_min_entropy because
        # we have calculated the entropy by javascript too and the results
        # may vary.
        password_min_entropy = (0.90 * password_min_entropy)

        generated_password = request.session.get('last_generated_password', '')
        if len(generated_password) > 0 and generated_password == value:
            # Don't validate the password if it is the generated password
            # That is, the user has filled out the form with the suggested
            # password
            return

        # Get a users e-mail addresses to make sure a user does not use one of those as password
        user = get_session_user(request, raise_on_not_logged_in = False)
        if not user:
            # User is resetting a forgotten password
            hash_code = request.matchdict['code']
            password_reset = request.db.reset_passwords.find_one({'hash_code': hash_code})
            user = request.userdb_new.get_user_by_mail(password_reset['email'])
        mail_addresses = [item.email for item in user.mail_addresses.to_list()]

        veredict = zxcvbn.password_strength(value, user_inputs=mail_addresses)

        if veredict.get('entropy', 0) < password_min_entropy:
            err = _('The password complexity is too weak.')
            raise colander.Invalid(node, localizer.translate(err))
示例#3
0
 def validate_password(self, _, password):
     """Validate the password if this is valid."""
     password_entropy = zxcvbn.password_strength(password)['entropy']
     if password_entropy < 20:
         raise ValidationError("Password too weak")
     password_hash = pwd_context.encrypt(password)
     return password_hash
示例#4
0
文件: controller.py 项目: Acen/core
    def __post_recovery(self, **post):
        try:
            data = Bunch(reset_password_form.native(post)[0])
        except Exception as e:
            if config.get('debug', False):
                raise
            return 'json:', dict(success=False, message=_("Unable to parse data."), data=post, exc=str(e))
        recovery = self.__get_recovery(data.email, data.recovery_key)
        if not recovery:
            return 'json:', dict(success=False, message=_("Sorry that recovery link has already expired"),
                                 location="/account/recover")
        passwd_ok, error_msg = _check_password(data.password, data.pass2)
        if not passwd_ok:
            return 'json:', dict(success=False, message=error_msg)

        #If the password isn't strong enough, reject it
        if(zxcvbn.password_strength(data.password).get("score") < MINIMUM_PASSWORD_STRENGTH):
            return 'json:', dict(success=False, message=_("Password provided is too weak. please add more characters, or include lowercase, uppercase, and special characters."), data=data)

        #set new password
        user = recovery.user
        user.password = data.password
        user.save()

        #remove recovery key
        recovery.delete()

        authenticate(user.username, data.password)

        return 'json:', dict(success=True, message=_("Password changed, forwarding ..."), location="/")
示例#5
0
    def collect_parameters(self):
        """Generate report

        :return: generator of progress: number of checks done
        """
        if self.dontcheck:
            raise ServerException("Dontcheck is set for %s" % self)
        logger.debug("Start collecting parameters for %s" % self)
        if not self.accessible():
            self.param_check_status = "server is not accessible"
            self.parameters = {}
            return
        else:
            self.param_check_status = "in progress"
        try:
            for result in self.rolecollection.collect_parameters(self.param_cmd, self.param_script):
                self.param_check_status = "in progress, %s checks" % result['progress']
                self.parameters = result['parameters']
                self.param_failures = result['failures']
                self.param_check_time = time.time()
                yield result['progress']
        except ServerException as se:
            self.param_check_status = "FAILED with ServerException: %s" % se
            self.parameters = {}
        else:
            if 'password' in self.account:
                self.parameters['password_strength'] = password_strength(
                    self.account['password'], user_inputs=[])['score']
            else:
                self.parameters['password_strength'] = 4
            self.param_check_status = "finished"
示例#6
0
def __process_passwords(passwords):
    out = []

    for p, users in passwords:
        out.append(__coloured_score(zxcvbn.password_strength(p)["score"], p))

    return ", ".join(out)
示例#7
0
    def post(self, **post):
        try:
            data = Bunch(register_form.native(post)[0])
        except Exception as e:
            if config.get('debug', False):
                raise
            return 'json:', dict(success=False, message=_("Unable to parse data."), data=post, exc=str(e))
        
        if not data.username or not data.email or not data.password or data.password != data.pass2:
            return 'json:', dict(success=False, message=_("Missing data or passwords do not match."), data=data)

        #Make sure that the provided email address is a valid form for an email address
        v = EmailValidator()
        email = data.email
        email, err = v.validate(email)
        if err:
            return 'json:', dict(success=False, message=_("Invalid email address provided."), data=data)
        
        #If the password isn't strong enough, reject it
        if(zxcvbn.password_strength(data.password).get("score") < MINIMUM_PASSWORD_STRENGTH):
            return 'json:', dict(success=False, message=_("Password provided is too weak. please add more characters, or include lowercase, uppercase, and special characters."), data=data)
        
        #Ensures that the provided username and email are lowercase
        user = User(data.username.lower(), data.email.lower(), active=True)
        user.password = data.password
        try:
            user.save()
        except ValidationError:
            return 'json:', dict(success=False, message=_("Invalid email address provided."), data=data)
        except NotUniqueError:
            return 'json:', dict(success=False, message=_("Either the username or email address provided is already taken."), data=data)
        
        authenticate(user.username, data.password)
        
        return 'json:', dict(success=True, location="/")
示例#8
0
 def eval_passwords(self, data):
     strength_results = {}
     for row in data:
         pass_check = zxcvbn.password_strength(row[2])
         # Remove the password from the results
         del pass_check['password']
         strength_results[row[0]] = pass_check
     return strength_results
示例#9
0
    def clean_key(self):
        # Password strength testing mostly done in JS; minimal validation here.
        password = self.cleaned_data.get('key')
        results = password_strength(password)

        if results['entropy'] < settings.PASSWORD_MINIMUM_ENTROPY:
            raise forms.ValidationError("Your password isn't strong enough.")
        return password
示例#10
0
    def all_passwords(self):
        results = self.table.search((Query().password.exists())
                                    & (Query().password != "")
                                    & self.only_users & self.only_enabled)

        return [(result["password"],
                 zxcvbn.password_strength(result["password"])["score"])
                for result in results]
示例#11
0
    def clean_key(self):
        # Password strength testing mostly done in JS; minimal validation here.
        password = self.cleaned_data.get('key')
        results = password_strength(password)

        if results['entropy'] < settings.PASSWORD_MINIMUM_ENTROPY:
            raise forms.ValidationError("Your password isn't strong enough.")
        return password
示例#12
0
    def post(self, **post):
        try:
            data = Bunch(register_form.native(post)[0])
        except Exception as e:
            if config.get('debug', False):
                raise
            return 'json:', dict(success=False,
                                 message=_("Unable to parse data."),
                                 data=post,
                                 exc=str(e))

        if not data.username or not data.email or not data.password or data.password != data.pass2:
            return 'json:', dict(
                success=False,
                message=_("Missing data or passwords do not match."),
                data=data)

        #Make sure that the provided email address is a valid form for an email address
        v = EmailValidator()
        email = data.email
        email, err = v.validate(email)
        if err:
            return 'json:', dict(success=False,
                                 message=_("Invalid email address provided."),
                                 data=data)

        #If the password isn't strong enough, reject it
        if (zxcvbn.password_strength(data.password).get("score") <
                MINIMUM_PASSWORD_STRENGTH):
            return 'json:', dict(
                success=False,
                message=
                _("Password provided is too weak. please add more characters, or include lowercase, uppercase, and special characters."
                  ),
                data=data)

        #Ensures that the provided username and email are lowercase
        user = User(data.username.lower(), data.email.lower(), active=True)
        user.password = data.password
        try:
            user.save()
        except ValidationError:
            return 'json:', dict(success=False,
                                 message=_("Invalid email address provided."),
                                 data=data)
        except NotUniqueError:
            return 'json:', dict(
                success=False,
                message=
                _("Either the username or email address provided is already taken."
                  ),
                data=data)

        authenticate(user.username, data.password)

        return 'json:', dict(success=True, location="/")
 def __init__(self, password='', username=''):
     if args.basic:
         self.basic = BasicAnalysis(password)
         self.basic.categorize(username)
     if args.zxcvbn:
         try:
             self.zxcvbn = zxcvbn.password_strength(password)
             #save memory on objects we dont use
             self.zxcvbn = {"crack_time":self.zxcvbn["crack_time"], "score":self.zxcvbn["score"]}
         except OverflowError:
             raise OverflowError #pass it back down, and we'll ignore this one.
示例#14
0
文件: views.py 项目: jmesa/fame-1
def valid_new_password(password, confirmation):
    strength = password_strength(password)

    if password != confirmation:
        flash('Password confirmation differs from new password.', 'danger')
        return False
    elif strength['score'] <= 2:
        flash('New password is too weak. Estimated cracking time is {}.'.format(strength['crack_time_display']), 'danger')
        return False

    return True
示例#15
0
def run(db, args):
    total, local_users, domain_users, computers = db.counts

    print("cracke-dit report for {}\n".format(args.domain))
    print("Local / Domain users:\t{}/{}".format(local_users, domain_users))

    if not args.only_enabled:
        print("Enabled / disabled users:\t{}/{}".format(*db.user_counts))

    if not args.only_users:
        print("Computer accounts:\t{}\t{:.2f}%".format(computers, (computers / total) * 100))

    cracked, blank, historic = db.password_stats
    print("Passwords cracked:\t{}/{}\t{:.2f}%".format(cracked, total, (cracked / total) * 100))
    print("Historic passwords:\t{}\t{:.2f}%".format(historic, (historic / total) * 100))

    only_alpha, with_special, only_digits = db.password_composition_stats
    print(UNDERLINE + "\nPassword composition" + END)
    print("Only alphanumeric:\t{}\t{:.2f}%".format(only_alpha, (only_alpha / total) * 100))
    print("Only digits:\t{}\t{:.2f}%".format(only_digits, (only_digits / total) * 100))
    print("With 'special char':\t{}\t{:.2f}%".format(with_special, (with_special / total) * 100))

    headers = ["Password", "Length", "Count", "Score", "Pwned #", "Users"]
    fmt_lambda = lambda password, count, score, users: [password, len(password), count, __coloured_score(score), __get_usage(password) if not args.no_hibp else '', __process_users(users)]
    default_align = [">", "<", "<", "<", "<", ""]

    top_passwords = db.get_passwords(sortby=lambda (password, count, score, users): (count, score, len(password)), reverse=True, limit=args.limit)
    __print_table(title="Top {} Passwords (by use, score)".format(args.limit), headers=headers, align=default_align,
                  values=top_passwords, format=fmt_lambda)

    bad_pass = db.get_passwords(sortby=lambda (password, count, score, users): (zxcvbn.password_strength(password)["score"], len(password), len(users)), reverse=False, limit=args.limit)
    __print_table(title="Top {} Worst Passwords (by score, length)".format(args.limit), headers=headers,
                  align=default_align, values=bad_pass, format=fmt_lambda)

    passwords = db.get_passwords_where(lambda password: password != "")
    __graph_passwords_containing("Passwords containing months", passwords, OrderedDict([(calendar.month_name[m], 0) for m in range(1, 13)]))
    __graph_passwords_containing("Passwords containing days", passwords, OrderedDict([(calendar.day_name[d], 0) for d in range(0, 7)]))

    print(UNDERLINE + "\nPassword length distribution" + END)
    grpd_passwords = ((p, len(list(count))) for p, count in itertools.groupby(sorted(passwords, key=lambda r: len(r["password"])), lambda r: len(r["password"])))
    keys, vals = map(list, zip(*grpd_passwords))
    vals_percents = [" ({:.2f}%)".format((v / total) * 100) for v in vals]
    __print_graph(keys, vals, vals_percents)

    if historic > 0:
        __print_table(title="Users historic passwords (top {})".format((args.limit)),
                      headers=["     User     ", "# Passwords", "Passwords"],
                      align=[">", "<", ""], values=db.get_historic_passwords(args.limit),
                      format=lambda user, passwords: [user, len(passwords), __process_passwords(passwords)])
示例#16
0
    def get_passwords(self, sortby, reverse=True, limit=10):
        results = sorted(
            self.table.search((Query().password.exists()) & self.only_users
                              & self.only_enabled),
            key=lambda r: r["password"])
        passwords = ((password, len(list(count)))
                     for password, count in itertools.groupby(
                         results, lambda r: r["password"]))

        return sorted(list(
            (password, count, zxcvbn.password_strength(password)["score"],
             self.__get_users_with_password(password))
            for password, count in passwords),
                      key=sortby,
                      reverse=reverse)[:limit]
示例#17
0
文件: controller.py 项目: Acen/core
 def entropy(self, **query):
     # Remove the timestamp
     query.pop('ts', None)
     
     # Make sure the user provides only a password
     if set(query.keys()) - {'password'}:
         raise HTTPForbidden()
     
     password = query.get("password")
     strong = False
     
     # If the password has a score of greater than 2, allow it
     if(zxcvbn.password_strength(password).get("score") > 2):
         strong = True
     
     return 'json:', dict(approved=strong, query={str(k): v for k, v in query.items()})
示例#18
0
    def entropy(self, **query):
        #Remove the timestamp
        query.pop('ts', None)

        #Make sure the user provides only a password
        if set(query.keys()) - {'password'}:
            raise HTTPForbidden()

        password = query.get("password")
        strong = False

        #If the password has a score of greater than 2, allow it
        if (zxcvbn.password_strength(password).get("score") > 2):
            strong = True

        return 'json:', dict(approved=strong,
                             query={str(k): v
                                    for k, v in query.items()})
示例#19
0
文件: users.py 项目: xiongzx/pcapdb
        def validate(self, data):
            """Make sure the passwords match and are reasonably strong."""

            password = data['password']
            password2 = data['password2']
            if password != password2:
                raise serializers.ValidationError("Passwords do not match.")

            pw_results = zxcvbn.password_strength(password)
            strength = pw_results['score']

            if strength < settings.PASSWORD_STRENGTH_MIN:
                raise serializers.ValidationError(
                    "Insufficient password strength. Scored {}/4. "
                    "Estimated time to crack: {}".format(
                        strength, pw_results['crack_time_display']))

            return data
示例#20
0
文件: forms.py 项目: gazoon/icemad
    def password_score(self):
        """
        This function calculates scores of strength of password.

        Returns:
            Float. Scores from 0 to 100.
        """
        password = self.data.get('password') or ''
        min_length = self.fields['password'].min_length
        if len(password) < min_length:
            return len(password) * PASSWORD_LENGTH_BORDER_SCORE / min_length
        strength = password_strength(password)['crack_time']
        strength = math.log10(strength)
        max_strength = math.log10(PASSWORD_MAX_STRENGTH)
        strength = min(strength, max_strength)
        strength = max(strength, 0)
        initial_scores = PASSWORD_LENGTH_BORDER_SCORE
        max_score = PASSWORD_MAX_SCORE - PASSWORD_LENGTH_BORDER_SCORE
        return initial_scores + strength * max_score / max_strength
示例#21
0
    def __call__(self, node, value):
        request = node.bindings.get('request')
        localizer = get_localizer(request)
        settings = request.registry.settings
        value = value.replace(" ", "")
        password_min_entropy = int(settings.get('password_entropy', 60))

        # We accept a 10% of variance in password_min_entropy because
        # we have calculated the entropy by javascript too and the results
        # may vary.
        password_min_entropy = (0.90 * password_min_entropy)

        generated_password = request.session.get('last_generated_password', '')
        if len(generated_password) > 0 and generated_password == value:
            # Don't validate the password if it is the generated password
            # That is, the user has filled out the form with the suggested
            # password
            return

        # Get a users e-mail addresses to make sure a user does not use one of those as password
        user = get_session_user(request, raise_on_not_logged_in=False)
        if not user:
            # User is resetting a forgotten password
            hash_code = request.matchdict['code']
            password_reset = request.db.reset_passwords.find_one(
                {'hash_code': hash_code})

            if password_reset.get('eppn'):
                user = request.userdb_new.get_user_by_eppn(
                    password_reset['eppn'])

            # Legacy password reset codes were connected to the user by email
            elif password_reset.get('email'):
                user = request.userdb_new.get_user_by_mail(
                    password_reset['email'])

        mail_addresses = [item.email for item in user.mail_addresses.to_list()]

        veredict = zxcvbn.password_strength(value, user_inputs=mail_addresses)

        if veredict.get('entropy', 0) < password_min_entropy:
            err = _('The password complexity is too weak.')
            raise colander.Invalid(node, localizer.translate(err))
示例#22
0
    def _get_good_password(self, user):
        password1 = self.grab("Password: "******"Password (again): ", True)
        if password2 != password1:
            self.error("Passwords do not match, try again.")
            return None

        blacklist = [
            user.username,
            user.first_name,
            user.last_name,
        ]
        check = zxcvbn.password_strength(password1, blacklist)
        if check['score'] < self.PASSWORD_MIN_SCORE:
            self.error("Password is too weak (bruteforce: %s)", check['crack_time_display'])
            return None

        self.success("Password is strong enough (bruteforce: %s)", check['crack_time_display'])
        return password1
示例#23
0
    def __post_recovery(self, **post):
        try:
            data = Bunch(reset_password_form.native(post)[0])
        except Exception as e:
            if config.get('debug', False):
                raise
            return 'json:', dict(success=False,
                                 message=_("Unable to parse data."),
                                 data=post,
                                 exc=str(e))
        recovery = self.__get_recovery(data.email, data.recovery_key)
        if not recovery:
            return 'json:', dict(
                success=False,
                message=_("Sorry that recovery link has already expired"),
                location="/account/recover")
        passwd_ok, error_msg = _check_password(data.password, data.pass2)
        if not passwd_ok:
            return 'json:', dict(success=False, message=error_msg)

        #If the password isn't strong enough, reject it
        if (zxcvbn.password_strength(data.password).get("score") <
                MINIMUM_PASSWORD_STRENGTH):
            return 'json:', dict(
                success=False,
                message=
                _("Password provided is too weak. please add more characters, or include lowercase, uppercase, and special characters."
                  ),
                data=data)

        #set new password
        user = recovery.user
        user.password = data.password
        user.save()

        #remove recovery key
        recovery.delete()

        authenticate(user.username, data.password)

        return 'json:', dict(success=True,
                             message=_("Password changed, forwarding ..."),
                             location="/")
示例#24
0
文件: models.py 项目: omeinusch/Palco
    def set_password(self, new_password):
        if settings.USE_LDAP:
            import ldap

            l = ldap.initialize(settings.LDAP_HOST)
            l.set_option(ldap.OPT_REFERRALS, 0)
            l.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
            l.simple_bind_s(settings.LDAP_BIND_DN, settings.LDAP_BIND_PASS)
            dn = 'uid=%s,%s' % (self.user.username, settings.LDAP_SEARCH_PATH)
            l.passwd_s(dn, None, new_password)

        self.user.set_password(new_password)
        self.user.save()
        pws = password_strength(new_password)
        self.password_entropy = pws['entropy']
        self.password_score = pws['score']
        self.password_updated = datetime.now()
        self.password_force_change = False
        self.password_recovery_token = None
        self.save()
示例#25
0
 def entropy(self):
     if self.cache.get('entropy') is not None:
         return self.cache['entropy']
     if not self.string:
         return 0
     if len(self.string) > 100:
         check_str = self.string[:100]
     else:
         check_str = self.string
     try:
         entropy = zxcvbn.password_strength(check_str)['entropy']
     except UnicodeDecodeError:
         logger.warning(
             'Failed to get entropy due to unicode decode error.')
         entropy = 0
     except OverflowError:
         logger.warning('Failed to get entropy due to overflow error.')
         entropy = 0
     self.cache['entropy'] = entropy
     return self.cache['entropy']
示例#26
0
def create_trie_only():
    passwords_path = MAIN_DIR + 'rockyou-ascii.txt'  # for quick checks
    #passwords_path = MAIN_DIR + 'rockyou-ascii_3.txt' ##
    #
    another_trie_path = MAIN_DIR + 'myTrieYay.txt'
    all_names = []
    with open(passwords_path, 'rb') as ff:
        with open(TRIE_PATH, 'wb') as ww:
            # at the end of the file the format is broken. simply deleted it manually
            START = time()
            print("start:{}".format(START))
            #for line in all_data: #

            for line in ff:
                try:
                    tup = (line.split())
                    count = int(tup[0])
                    splitted_str = [x for x in tup[1:]]
                    pw = ' '.join(splitted_str)
                    pw_ent_bits = password_strength(pw)['entropy']
                    all_names.append(pw)
                    typos = [
                        tt[0] for tt in get_pos_typos(pw, pw_ent_bits, 1, NNN)
                    ]
                    all_names = all_names + typos
                except UnicodeError as e:  # shouldn't happen because the file manipulation is done before
                    print "line: {}".format(line)
                    raise e
                except ValueError as e:
                    # password contains space so split fails
                    print "line: {}".format(line)
                    raise e
                except KeyError as e:
                    print("KeyError")
                    raise e
            print "finished collecting"
            all_for_trie = marisa_trie.Trie(all_names)
            print "trie createed writing to file"
            all_for_trie.save(another_trie_path)
            for word, code in all_for_trie.items():
                ww.write(" ".join([str(code), str(word), '\n']))
示例#27
0
文件: pwgen.py 项目: Heleen/pwgen
def main(argv={}):
    password = Password(argv).generate()

    """ Copy the password to clipboard? """
    if not argv['--no-clipboard']:
        try:
            import xerox
            xerox.copy(password)
        except ImportError:
            print no_xerox_error

    """ Print the password? """
    if argv['--print'] or argv['--no-clipboard']:
        print password

    """ Print password strength """
    try:
        from zxcvbn import password_strength
        strength = password_strength(password)
        print 'crack time: %s, score: %s out of 4' % (strength['crack_time_display'], str(strength['score']))
    except ImportError:
        print no_zxcvbn_error
 def entropy(self):
     if self.cache.get('entropy') is not None:
         return self.cache['entropy']
     if not self.string:
         return 0
     if len(self.string) > 100:
         check_str = self.string[:100]
     else:
         check_str = self.string
     try:
         entropy = zxcvbn.password_strength(check_str)['entropy']
     except UnicodeDecodeError:
         logger.warning(
             'Failed to get entropy due to unicode decode error.'
         )
         entropy = 0
     except OverflowError:
         logger.warning(
             'Failed to get entropy due to overflow error.'
         )
         entropy = 0
     self.cache['entropy'] = entropy
     return self.cache['entropy']
示例#29
0
    def __call__(self, node, value):
        request = node.bindings.get('request')
        localizer = get_localizer(request)
        settings = request.registry.settings
        value = value.replace(" ", "")
        password_min_entropy = int(settings.get('password_entropy', 60))

        # We accept a 10% of variance in password_min_entropy because
        # we have calculated the entropy by javascript too and the results
        # may vary.
        password_min_entropy = (0.90 * password_min_entropy)

        generated_password = request.session.get('last_generated_password', '')
        if len(generated_password) > 0 and generated_password == value:
            # Don't validate the password if it is the generated password
            # That is, the user has filled out the form with the suggested
            # password
            return

        veredict = zxcvbn.password_strength(value)

        if veredict.get('entropy', 0) < password_min_entropy:
            err = _('The password complexity is too weak.')
            raise colander.Invalid(node, localizer.translate(err))
示例#30
0
def test_password_strength(password, user_inputs=None):
    '''Wrapper around zxcvbn.password_strength'''
    result = zxcvbn.password_strength(password, user_inputs)
    result['feedback'] = get_feedback(result['score'],
                                      result['match_sequence'])
    return result
示例#31
0
def zxcvbn_getpass(prompt, prefix='', allow_empty=True):
    """ Similar to getpass.getpass, but shows password strength while typing """
    pw = None
    current = ''
    checked_strength_of = None
    prompt_offset = len(prefix) + len(prompt)
    purge_stdin()
    sys.stderr.write('\033[1G\033[K')
    sys.stderr.write(prefix + prompt)
    sys.stderr.flush()
    interacted = False
    with raw_mode():
        while True:
            if interacted and not pw and checked_strength_of != current:
                strength = zxcvbn.password_strength(current)
                checked_strength_of = current
                text = '%-4s %3sb %s' % (strength['score'] * '*',
                                         int(strength['entropy']),
                                         strength['crack_time_display'])
                sys.stderr.write('\033[55G\033[K%s\033[%sG' %
                                 (text, prompt_offset + 1))
                sys.stderr.flush()
            c = sys.stdin.read(1)
            interacted = True
            if c == '\r' or c == '\n':
                if not current and not pw:
                    if allow_empty:
                        sys.stderr.write('\033[K\n')
                        sys.stderr.flush()
                        return None
                    sys.stderr.write('\033[1G\033[K')
                    new_prompt = prefix + 'No password given.  Retry: '
                    sys.stderr.write(new_prompt)
                    prompt_offset = len(new_prompt)
                    sys.stderr.flush()
                    interacted = False
                    continue
                if pw:
                    if pw != current:
                        sys.stderr.write('\033[1G\033[K')
                        new_prompt = prefix + 'Passwords did not match.  Retry: '
                        sys.stderr.write(new_prompt)
                        prompt_offset = len(new_prompt)
                        sys.stderr.flush()
                        pw = None
                        current = ''
                        interacted = False
                        continue
                    sys.stderr.write('\033[K\n')
                    sys.stderr.flush()
                    return pw
                pw = current
                current = ''
                sys.stderr.write('\033[1G\033[K')
                new_prompt = prefix + 'Repeat to verify: '
                sys.stderr.write(new_prompt)
                prompt_offset = len(new_prompt)
                sys.stderr.flush()
            elif c in string.printable:
                current += c
            elif c == '\x17':  # C-w
                current = current[:current.rfind(' ', 0, -1) + 1]
            elif c == '\x15':  # C-u
                current = ''
            elif c == '\x7f':  # backspace
                current = current[:-1]
            elif c == '\x03':  # C-c
                raise KeyboardInterrupt
            else:
                sys.stderr.write('\033[55G\033[Kignored key %r\033[%sG' %
                                 (c, prompt_offset + 1))
                sys.stderr.flush()
def entropy(w):
    try:
        return password_strength(w)['entropy']
    except Exception as e:
        print (e)
        return -1
示例#33
0
文件: terminal.py 项目: bwesterb/pol
def zxcvbn_getpass(prompt, prefix='', allow_empty=True):
    """ Similar to getpass.getpass, but shows password strength while typing """
    pw = None
    current = ''
    checked_strength_of = None
    prompt_offset = len(prefix) + len(prompt)
    purge_stdin()
    sys.stderr.write('\033[1G\033[K')
    sys.stderr.write(prefix + prompt)
    sys.stderr.flush()
    interacted = False
    with raw_mode():
        while True:
            if interacted and not pw and checked_strength_of != current:
                strength = zxcvbn.password_strength(current)
                checked_strength_of = current
                text = '%-4s %3sb %s' % (strength['score'] * '*',
                                int(strength['entropy']),
                                strength['crack_time_display'])
                sys.stderr.write('\033[55G\033[K%s\033[%sG' % (
                            text, prompt_offset + 1))
                sys.stderr.flush()
            c = sys.stdin.read(1)
            interacted = True
            if c == '\r' or c == '\n':
                if not current and not pw:
                    if allow_empty:
                        sys.stderr.write('\033[K\n')
                        sys.stderr.flush()
                        return None
                    sys.stderr.write('\033[1G\033[K')
                    new_prompt = prefix+'No password given.  Retry: '
                    sys.stderr.write(new_prompt)
                    prompt_offset = len(new_prompt)
                    sys.stderr.flush()
                    interacted = False
                    continue
                if pw:
                    if pw != current:
                        sys.stderr.write('\033[1G\033[K')
                        new_prompt = prefix+'Passwords did not match.  Retry: '
                        sys.stderr.write(new_prompt)
                        prompt_offset = len(new_prompt)
                        sys.stderr.flush()
                        pw = None
                        current = ''
                        interacted = False
                        continue
                    sys.stderr.write('\033[K\n')
                    sys.stderr.flush()
                    return pw
                pw = current
                current = ''
                sys.stderr.write('\033[1G\033[K')
                new_prompt = prefix + 'Repeat to verify: '
                sys.stderr.write(new_prompt)
                prompt_offset = len(new_prompt)
                sys.stderr.flush()
            elif c in string.printable:
                current += c
            elif c == '\x17': # C-w
                current = current[:current.rfind(' ', 0, -1)+1]
            elif c == '\x15': # C-u
                current = ''
            elif c == '\x7f': # backspace
                current = current[:-1]
            elif c == '\x03': # C-c
                raise KeyboardInterrupt
            else:
                sys.stderr.write('\033[55G\033[Kignored key %r\033[%sG' % (
                                             c, prompt_offset + 1))
                sys.stderr.flush()
示例#34
0
def test_password_strength(password, user_inputs=None):
	'''Wrapper around zxcvbn.password_strength'''
	result = zxcvbn.password_strength(password, user_inputs)
	result['feedback'] = get_feedback(result['score'], result['match_sequence'])
	return result
示例#35
0
def get_pos_typos(pw, pw_ent_bits, count=1, req_len=0):
    if not pw:
        return []  # TODO CHANGE
    pw_press = TO_KEY_SEQ(pw)
    # caps lock on/off
    p_caps = 10.9
    p_shift_first = 4.5  # flipped, either on or off
    p_added_end = 4.6
    p_added_front = 1.3
    p_shift_last = 0.2
    p_prox = 21.8
    # out of 100
    sum_p = p_caps + p_shift_first + p_added_front + p_added_end + p_shift_last + p_prox

    #
    sum_p -= p_added_front  #
    p_caps = (count * p_caps) / sum_p
    p_shift_first = (count * p_shift_first) / sum_p
    p_added_end = (count * p_added_end) / sum_p
    #p_added_front = (count * p_added_front) / sum_p
    p_shift_last = (count * p_shift_last) / sum_p
    p_prox = (count * p_prox) / sum_p
    #

    # small_sum = p_caps+p_shift_first + p_added_end + p_shift_last + p_prox ## TODO REMOVE
    # print "initial sum: {}".format(small_sum) ## TODO REMOVE
    many_typos = []
    try:
        t_caps = ''.join([CAPS, pw_press
                          ]) if pw_press[0] != CAPS else pw_press[1:]
        t_shift_first = ''.join([SHIFT, pw_press
                                 ]) if pw_press[0] != SHIFT else pw_press[1:]
        t_shift_last = ''.join([
            pw_press[:-1], SHIFT, pw_press[-1]
        ]) if pw_press[-2] != SHIFT else ''.join([pw_press[:-2], pw_press[-1]])
        tmp_typo_list = [(t_caps, p_caps), (t_shift_last, p_shift_last),
                         (t_shift_first, p_shift_first)]
    except IndexError as e:
        print "skipped steps for {}. Index Error".format(pw)
    #
    for (typo, pp) in tmp_typo_list:
        typo = BACK_TO_WORD(typo)  ###
        typo_ent_bits = password_strength(typo)['entropy']  ###
        too_weak = (typo_ent_bits < MIN_ENT) or (
            (typo_ent_bits - pw_ent_bits) < MIN_REL_ENT)  ###
        if too_weak:
            continue
        many_typos.append((typo, pp))

    # added end - only digits
    zero = ord('0')
    for i in xrange(0, 10):
        add_ch = chr(i + zero)
        typo = BACK_TO_WORD(''.join([pw_press, add_ch]))
        typo_ent_bits = password_strength(typo)['entropy']  ###
        too_weak = (typo_ent_bits < MIN_ENT) or (
            (typo_ent_bits - pw_ent_bits) < MIN_REL_ENT)  ###
        if too_weak:
            continue
        many_typos.append((typo, p_added_end / 10))
    # addedFront - TODO

    # prox
    length = len(pw_press)
    # print length
    for i in xrange(length):
        c = pw_press[i]
        nearby_chrs = filter(lambda x: not UPPER(x), list(NEARBY_KEYS(c)))
        nearby_len = len(nearby_chrs)
        if not nearby_len:
            continue
        each_p = (1.0 / length) * p_prox * (1.0 / nearby_len)
        for c_t in nearby_chrs:
            typo = BACK_TO_WORD(''.join([pw_press[:i], c_t, pw_press[i + 1:]]))
            typo_ent_bits = password_strength(typo)['entropy']  ###
            too_weak = (typo_ent_bits < MIN_ENT) or (
                (typo_ent_bits - pw_ent_bits) < MIN_REL_ENT)  ###
            if too_weak:
                continue
            many_typos.append((typo, each_p))

    # getting only the top length typos
    try:
        if req_len:
            sum_prob_of_req = 0
            ii = min(req_len, len(many_typos)) - 1
            least_p = many_typos[ii][1]
            m_t_len = len(many_typos)
            while (ii < m_t_len) and (many_typos[ii][1] == least_p):
                ii += 1
            req_typos = many_typos[:ii]
            for jj in xrange(ii):
                sum_prob_of_req += req_typos[jj][1]
            assert sum_prob_of_req < 1.0000001  # there's a bit of miss-accuracy with float sums
            # if sum_prob_of_req > 1.000000001: ###### there's a bit of miss-accuracy with float sums
            # 	print 'prob_sum:', sum_prob_of_req
            # 	print "bool:", sum_prob_of_req > 1.0
            # 	print "pw '{}'' with too much prob, {} ".format(pw,sum_prob_of_req)
            # 	for ttt in req_typos:
            # 		print ttt
            for jj in xrange(len(req_typos)):
                tt, tt_pp = req_typos[jj]
                req_typos[jj] = (tt, tt_pp / sum_prob_of_req)

    except IndexError as e:
        print "req_L: {}, ii:{}".format(req_len, ii)
        print "pmany_typos[ii]:{}".format(many_typos[ii])

    return many_typos
示例#36
0
 def __call__(self, value):
     res = zxcvbn.password_strength(value)
     if res.get('entropy') < self.password_minimum_entropy:
         raise ValidationError(self.message % _("Password is too weak"),
                               code=self.code)
示例#37
0
 def __call__(self,value):
     res = zxcvbn.password_strength(value)
     if res.get('entropy') < PASSWORD_MIN_ENTROPY:
         raise ValidationError(
             self.message % _("Password is too weak"),
             code=self.code)
def entropy(w):
    try:
        return password_strength(w)['entropy']
    except Exception as e:
        print(e)
        return -1
示例#39
0
__author__ = 'kyhwana'
import zxcvbn
import sys
passwordfile = open(sys.argv[1], 'r')
entropyscore = sys.argv[2]

for line in passwordfile:
    result = zxcvbn.password_strength(line.rstrip("\n"))
    if result["entropy"] > float(entropyscore):
        print("Password: "******"password"] + " Score:" + repr(result["score"]) + " Entropy:" + repr(result["entropy"]) )




示例#40
0
文件: entropy.py 项目: n3if/passplop
def entropy(str):
    return password_strength(str)
示例#41
0
def safe_secret_assignment(context):
    is_assignment = False
    is_target_likely_secret = False
    is_safe_secret_source = False
    is_hardcoded_string = False
    discounted_entropy_string = False
    entropy = 0
    entropy_per_char = 0

    if not context.string_val:
        return

    statement = context.statement["node"]
    if isinstance(statement, ast.Assign):
        is_assignment = True
        is_target_likely_secret = is_assignment_target_secret(context)
        if is_target_likely_secret:
            if isinstance(statement.value, ast.Call):
                f = statement.value.func
                func_name_parts = []
                while True:
                    if isinstance(f, ast.Attribute):
                        func_name_parts.insert(0, f.attr)
                        f = f.value
                    elif isinstance(f, ast.Name):
                        func_name_parts.insert(0, f.id)
                        source_name = ".".join(func_name_parts)
                        if source_name in SAFE_SECRET_SOURCES:
                            is_safe_secret_source = True
                        break
                    elif isinstance(f, ast.Str):
                        is_hardcoded_string = True
                        logging.warning("!!STRING!! %s" % str(func_name_parts))

                        string = context.string_val
                        discounted_entropy_string = any(
                            (pattern.search(string) for pattern in ENTROPY_PATTERNS_TO_DISCOUNT)
                        )
                        entropy = zxcvbn.password_strength(string)["entropy"]
                        entropy_per_char = entropy / float(len(string))
                        break
                    else:
                        logging.warning("Don't know what to do with type {}".format(type(f.value)))
                        break
            elif isinstance(statement.value, ast.Str):
                string = statement.value.s
                discounted_entropy_string = any((pattern.search(string) for pattern in ENTROPY_PATTERNS_TO_DISCOUNT))
                entropy = zxcvbn.password_strength(string)["entropy"]
                entropy_per_char = entropy / float(len(string))
                is_hardcoded_string = True
    else:  # not assignment -- let's just look at the string itself
        string = context.string_val
        discounted_entropy_string = any((pattern.search(string) for pattern in ENTROPY_PATTERNS_TO_DISCOUNT))
        entropy = zxcvbn.password_strength(string)["entropy"]
        entropy_per_char = entropy / float(len(string))

    # scoring
    confidence = 0
    if is_assignment:
        if is_target_likely_secret:
            if not is_hardcoded_string and not is_safe_secret_source:
                return bandit.Issue(
                    severity=bandit.MEDIUM,
                    confidence=bandit.LOW,
                    text="Unknown secret source assigned to '(%s)'" % assignment_target_pretty(context),
                )
            elif is_hardcoded_string and not discounted_entropy_string:
                confidence += 2
    if (entropy > 80 or (entropy > 40 and entropy_per_char > 3)) and not discounted_entropy_string:
        confidence += 1
    if entropy >= 120 and not discounted_entropy_string:
        confidence += 1

    debug = {
        "discounted_entropy_string": discounted_entropy_string,
        "entropy": entropy,
        "entropy_per_char": entropy_per_char,
        "is_target_likely_secret": is_target_likely_secret,
        "is_assignment": is_assignment,
        "is_hardcoded_string": is_hardcoded_string,
        "is_safe_secret_source": is_safe_secret_source,
    }
    # print(debug)

    if confidence >= 1:
        if confidence == 1:
            confidence = bandit.LOW
        elif confidence == 2:
            confidence = bandit.MEDIUM
        else:
            confidence = bandit.HIGH

        if is_assignment:
            return bandit.Issue(
                severity=confidence,
                confidence=confidence,
                text="Possible hardcoded secret assigned to '%s'" % assignment_target_pretty(context),
            )
        else:
            return bandit.Issue(
                severity=confidence,
                confidence=confidence,
                text="Possible hardcoded secret '%s...%s'" % (string[:4], string[-4:]),
            )
示例#42
0
def initiate():
    #file_path = MAIN_DIR + 'rockyou-withcount.txt'
    # file_path = MAIN_DIR + 'rockyou-ascii.txt' # for quick checks
    file_path = MAIN_DIR + 'rockyou-ascii_3.txt'  ##
    #with codecs.open(file_path,encoding ='utf-8',mode='rb') as ff: # TODO REMOVE
    with open(file_path, 'rb') as ff:
        # at the end of the file the format is broken. simply deleted it manually
        START = time()
        print("start:{}".format(START))
        pw_d = {}
        typo_d = {}
        #for line in all_data: #
        sum_all_users = 0
        for line in ff:
            try:
                tup = (line.split())
                count = int(tup[0])
                splitted_str = [x for x in tup[1:]]
                pw = ' '.join(splitted_str)
                sum_all_users += count
                if pw in pw_d:
                    cc = pw_d[pw]
                    pw_d[pw] = count + cc
                else:
                    pw_d[pw] = count

            except UnicodeError as e:  # shouldn't happen because the file manipulation is done before
                print "line: {}".format(line)
                raise e
            except ValueError as e:
                # password contains space so split fails
                print "line: {}".format(line)
                raise e
            except KeyError as e:
                print("KeyError")
                raise e
    # out of 'for', out of file
    # for now - pw_d format is-  pw_d[pw] = count
    for pw, pw_count in pw_d.iteritems():
        # on online attack - ALL weak psswords will be part of the possibilities (even if they're weak)
        #if ONLINE_ATTACK:
        pw_pp = float(pw_count) / sum_all_users
        # adding the pw as a possile "typo" - possible attack input
        try:
            typo_sum_pp, pws_with_this_typo = typo_d[pw]
            pws_with_this_typo.append((pw, 1))
            typo_d[pw] = (typo_sum_pp + 1, pws_with_this_typo)
        except KeyError:  # first time
            typo_d[pw] = (1, [(pw, 1)])

        pw_ent_bits = password_strength(pw)['entropy']
        # too_weak =  pw_ent_bits < MIN_ENT
        typos = get_pos_typos(pw, pw_ent_bits, 1, NNN)

        # a weak password might have a strong typo
        # therefore we're not skipping
        #if too_weak: # doesn't enter hashCache
        #	continue
        pw_d[pw] = (pw_pp, typos)

        for tt, tt_pp in typos:
            actual_tt_pp = tt_pp * pw_pp
            try:  #
                sum_p_of_typo, pws_with_this_typo = typo_d[tt]
                pws_with_this_typo.append((pw, actual_tt_pp))
                typo_d[tt] = (sum_p_of_typo + actual_tt_pp, pws_with_this_typo)
            except KeyError:  # first time
                typo_d[tt] = (actual_tt_pp, [(pw, actual_tt_pp)])

    print("empty in dic:{}".format('' in pw_d))  # TODO REMOVE
    print("Finished building the pw dict. len:{}".format(len(pw_d)))
    print("Finished building the typo dict. len:{}".format(len(typo_d)))

    print("Building marisa-trie")
    GLOBAL_TRIE = marisa_trie.Trie(
        [word in itertools.chain(pw_d.keys(), typo_d.keys())])

    pw_save_path = MAIN_DIR + 'pw_left.txt'
    typo_save_path = MAIN_DIR + 'typos_left.txt'
    print("Starting to build typo dict")

    # WE HAVE DUPLICATE PW from normalizing

    MAX_PW_PER_TYPO = 0
    with open(pw_save_path, 'wb') as write_pw:
        with open(typo_save_path, 'wb') as write_typo:

            print "converting to marisa-based-ids"

            pw_id_d = {}
            typo_id_d = {}

            # if ONLINE ATTACK then pws are in the typo_trie
            # better for continuity
            print "Creating id dicts, and writing to files"
            UTF8 = 'utf-8'
            for pw, (pw_pp, typo_and_p_list) in pw_d.iteritems():
                # print "pw:{}, count:{}, typ_lis:{}".format(pw,count,typ_lis) # TODO REMOVE
                pw_id = GLOBAL_TRIE.key_id(pw.decode(UTF8))
                typos_id_list = [(GLOBAL_TRIE.key_id((tt).decode(UTF8)), pp)
                                 for (tt, pp) in typ_lis]
                pw_id_d[pw_id] = (pw_pp, typos_id_list)
                #
                line = ' '.join([
                    str(pw_id),
                    str(pw_pp), ' '.join([
                        str(tt) + ' ' + str(pp) for (tt, pp) in typos_id_list
                    ]), '\n'
                ])
                write_pw.write(line)

            for typo, (sum_typo_pp, pw_lis) in typo_d.iteritems():
                # pw_list is [(pw1,p1),(pw2,p22),...]
                MAX_PW_PER_TYPO = max(MAX_PW_PER_TYPO, len(pw_lis))
                typo_id = GLOBAL_TRIE.key_id(typo.decode(UTF8))
                #try:
                pw_id_lis = [(GLOBAL_TRIE.key_id(pw.decode(UTF8)), pp)
                             for (pw, pp) in pw_lis]  # turn to int?
                # except ValueError as e: # TODO REMOVE
                # 	print pw_lis
                # 	raise e
                typo_id_d[typo_id] = (sum_typo_pp, pw_id_lis)  # turn to int ?
                #
                #line = str(typo_id) + ' ' +str(count) + ' ' + ' '.join([str(pw) for pw in pw_id_lis])
                line = ' '.join([
                    str(typo_id),
                    str(sum_typo_pp), ' '.join([
                        str(pw) + ' ' + str(pw_pp) for (pw, pw_pp) in pw_id_lis
                    ]), '\n'
                ])
                write_typo.write(line)

    print "finished converting!"
    print "MAX : {}".format(MAX_PW_PER_TYPO)
    print " saving marisa trie :)"
    marisa_path = MAIN_DIR + "marisa_all.txt"
    with open(marisa_path, 'wb') as ff:
        for word, code in GLOBAL_TRIE.items():
            ff.write(' '.join(str(code), str(word)))
    print "finished writing marisa_trie"
    my_count = 0
    for typo in typo_d:
        print("t:{},c:{}".format(typo, typo_d[typo]))
        my_count += 1
        if my_count >= 5:
            break
    my_count = 0
    for pw, (typ_lis) in pw_d.iteritems():
        print("pw: {}, count:{}, typos: {}".format(pw, count, typ_lis))
        my_count += 1
        if my_count >= 5:
            break
    END = time()
    print("ended: {}".format(END))

    return pw_id_d, typo_id_d, GLOBAL_TRIE
示例#43
0
__author__ = 'kyhwana'
import zxcvbn
import sys
passwordfile = open(sys.argv[1], 'r')
entropyscore = sys.argv[2]

for line in passwordfile:
    result = zxcvbn.password_strength(line.rstrip("\n"))
    if result["entropy"] > float(entropyscore):
        print("Password: "******"password"] + " Score:" +
              repr(result["score"]) + " Entropy:" + repr(result["entropy"]))
 def __call__(self, value):
     res = zxcvbn.password_strength(value)
     if res.get('entropy') < PASSWORD_MIN_ENTROPY:
         raise ValidationError(PASSWORD_MIN_ENTROPY_MESSAGE, code=self.code)
示例#45
0
文件: models.py 项目: omeinusch/Palco
 def update_password_meta(self, raw_password):
     pws = password_strength(raw_password)
     self.password_entropy = pws['entropy']
     self.password_score = pws['score']
     self.save()
示例#46
0
文件: controller.py 项目: Acen/core
    def post(self, **post):
        try:
            data = Bunch(post)
        except Exception as e:
            if config.get('debug', False):
                raise
            return 'json:', dict(success=False, message=_("Unable to parse data."), data=post, exc=str(e))

        query = dict(active=True)
        query[b'username'] = data.id

        query_user = User.objects(**query).first()
        if query_user.id != user.id:
            raise HTTPForbidden

        if data.form == "changepassword":
            passwd_ok, error_msg = _check_password(data.passwd, data.passwd1)

            if not passwd_ok:
                return 'json:', dict(success=False, message=error_msg, data=data)

            if isinstance(data.old, unicode):
                data.old = data.old.encode('utf-8')

            if not User.password.check(user.password, data.old):
                return 'json:', dict(success=False, message=_("Old password incorrect."), data=data)

            #If the password isn't strong enough, reject it
            if(zxcvbn.password_strength(data.passwd).get("score") < MINIMUM_PASSWORD_STRENGTH):
                return 'json:', dict(success=False, message=_("Password provided is too weak. please add more characters, or include lowercase, uppercase, and special characters."), data=data)

            user.password = data.passwd
            user.save()
        elif data.form == "addotp":
            if isinstance(data.password, unicode):
                data.password = data.password.encode('utf-8')

            identifier = data.otp
            client = yubico.Yubico(
                config['yubico.client'],
                config['yubico.key'],
                boolean(config.get('yubico.secure', False))
            )

            if not User.password.check(user.password, data.password):
                return 'json:', dict(success=False, message=_("Password incorrect."), data=data)

            try:
                status = client.verify(identifier, return_response=True)
            except:
                return 'json:', dict(success=False, message=_("Failed to contact YubiCloud."), data=data)

            if not status:
                return 'json:', dict(success=False, message=_("Failed to verify key."), data=data)

            if not User.addOTP(user, identifier[:12]):
                return 'json:', dict(success=False, message=_("YubiKey already exists."), data=data)
        elif data.form == "removeotp":
            identifier = data.otp

            if not User.removeOTP(user, identifier[:12]):
                return 'json:', dict(success=False, message=_("YubiKey invalid."), data=data)

        elif data.form == "configureotp":
            if isinstance(data.password, unicode):
                data.password = data.password.encode('utf-8')
            rotp = True if 'rotp' in data else False

            if not User.password.check(user.password, data.password):
                return 'json:', dict(success=False, message=_("Password incorrect."), data=data)
            
            user.rotp = rotp
            user.save()
            
        #Handle the user attempting to delete their account
        elif data.form == "deleteaccount":
            if isinstance(data.passwd, unicode):
                data.passwd = data.passwd.encode('utf-8')
             
            #Make the user enter their username so they know what they're doing.
            if not user.username == data.username.lower():
                return 'json:', dict(success=False, message=_("Username incorrect."), data=data)
        
            #Check whether the user's supplied password is correct
            if not User.password.check(user.password, data.passwd):
                return 'json:', dict(success=False, message=_("Password incorrect."), data=data)
                
            #Make them type "delete" exactly
            if not data.confirm == "delete":
                return 'json:', dict(success=False, message=_("Delete was either misspelled or not lowercase."), data=data)
            
            #Delete the user account and then deauthenticate the browser session
            log.info("User %s authorized the deletion of their account.", user)
            user.delete()
            deauthenticate()
            
            #Redirect user to the root of the server instead of the settings page
            return 'json:', dict(success=True, location="/")
            
        #Handle the user attempting to change the email address associated with their account
        elif data.form == "changeemail":
            if isinstance(data.passwd, unicode):
                data.passwd = data.passwd.encode('utf-8')
        
            #Check whether the user's supplied password is correct
            if not User.password.check(user.password, data.passwd):
                return 'json:', dict(success=False, message=_("Password incorrect."), data=data)

            #Check that the two provided email addresses match
            if not data.newEmail.lower() == data.newEmailConfirm.lower():
                return 'json:', dict(success=False, message=_("Provided email addresses do not match."), data=data)
            
            #Make sure that the provided email address is a valid form for an email address
            v = EmailValidator()
            email = data.newEmail
            email, err = v.validate(email)
            if err:
                return 'json:', dict(success=False, message=_("Invalid email address provided."), data=data)
                
            #Make sure that the new email address is not already taken
            count = User.objects.filter(**{"email": data.newEmail.lower()}).count()
            if not count == 0:
                return 'json:', dict(success=False, message=_("The email address provided is already taken."), data=data)
       
            #Change the email address in the database and catch any email validation exceptions that mongo throws
            user.email = data.newEmail.lower()
            try:
                user.save()
            except ValidationError:
                return 'json:', dict(success=False, message=_("Invalid email address provided."), data=data)
            except NotUniqueError:
                return 'json:', dict(success=False, message=_("The email address provided is already taken."), data=data)
        
        #Handle the user attempting to merge 2 accounts together
        elif data.form == "mergeaccount":
            if isinstance(data.passwd, unicode):
                data.passwd = data.passwd.encode('utf-8')
                
            if isinstance(data.passwd2, unicode):
                data.passwd2 = data.passwd2.encode('utf-8')
                
            #Make the user enter their username so they know what they're doing.
            if user.username != data.username.lower() and user.username != data.username:
                return 'json:', dict(success=False, message=_("First username incorrect."), data=data)
                
            #Check whether the user's supplied password is correct
            if not User.password.check(user.password, data.passwd):
                return 'json:', dict(success=False, message=_("First password incorrect."), data=data)
                
            #Make sure the user isn't trying to merge their account into itself.
            if data.username.lower() == data.username2.lower():
                return 'json:', dict(success=False, message=_("You can't merge an account into itself."), data=data)
                
            #Make the user enter the second username so we can get the User object they want merged in.
            if not User.objects(username=data.username2.lower()) and not User.objects(username=data.username2):
                return 'json:', dict(success=False, message=_("Unable to find user by second username."), data=data)
                
            other = User.objects(username=data.username2).first()
            if not other:
                other = User.objects(username=data.username2.lower()).first()
                
            #Check whether the user's supplied password is correct
            if not User.password.check(other.password, data.passwd2):
                return 'json:', dict(success=False, message=_("Second password incorrect."), data=data)
                
            #Make them type "merge" exactly
            if data.confirm != "merge":
                return 'json:', dict(success=False, message=_("Merge was either misspelled or not lowercase."), data=data)
                
            log.info("User %s merged account %s into %s.", user.username, other.username, user.username)
            user.merge(other)
            
            #Redirect user to the root of the server instead of the settings page
            return 'json:', dict(success=True, location="/")
            
        else:
            return 'json:', dict(success=False, message=_("Form does not exist."), location="/")
        
        return 'json:', dict(success=True, location="/account/settings")
示例#47
0
    def post(self, **post):
        try:
            data = Bunch(post)
        except Exception as e:
            if config.get('debug', False):
                raise
            return 'json:', dict(success=False,
                                 message=_("Unable to parse data."),
                                 data=post,
                                 exc=str(e))

        query = dict(active=True)
        query[b'username'] = data.id

        user = User.objects(**query).first()

        if data.form == "changepassword":
            passwd_ok, error_msg = _check_password(data.passwd, data.passwd1)

            if not passwd_ok:
                return 'json:', dict(success=False,
                                     message=error_msg,
                                     data=data)

            if isinstance(data.old, unicode):
                data.old = data.old.encode('utf-8')

            if not User.password.check(user.password, data.old):
                return 'json:', dict(success=False,
                                     message=_("Old password incorrect."),
                                     data=data)

            #If the password isn't strong enough, reject it
            if (zxcvbn.password_strength(data.passwd).get("score") <
                    MINIMUM_PASSWORD_STRENGTH):
                return 'json:', dict(
                    success=False,
                    message=
                    _("Password provided is too weak. please add more characters, or include lowercase, uppercase, and special characters."
                      ),
                    data=data)

            user.password = data.passwd
            user.save()
        elif data.form == "addotp":
            if isinstance(data.password, unicode):
                data.password = data.password.encode('utf-8')

            identifier = data.otp
            client = yubico.Yubico(config['yubico.client'],
                                   config['yubico.key'],
                                   boolean(config.get('yubico.secure', False)))

            if not User.password.check(user.password, data.password):
                return 'json:', dict(success=False,
                                     message=_("Password incorrect."),
                                     data=data)

            try:
                status = client.verify(identifier, return_response=True)
            except:
                return 'json:', dict(success=False,
                                     message=_("Failed to contact YubiCloud."),
                                     data=data)

            if not status:
                return 'json:', dict(success=False,
                                     message=_("Failed to verify key."),
                                     data=data)

            if not User.addOTP(user, identifier[:12]):
                return 'json:', dict(success=False,
                                     message=_("YubiKey already exists."),
                                     data=data)
        elif data.form == "removeotp":
            identifier = data.otp

            if not User.removeOTP(user, identifier[:12]):
                return 'json:', dict(success=False,
                                     message=_("YubiKey invalid."),
                                     data=data)

        elif data.form == "configureotp":
            if isinstance(data.password, unicode):
                data.password = data.password.encode('utf-8')
            rotp = True if 'rotp' in data else False

            if not User.password.check(user.password, data.password):
                return 'json:', dict(success=False,
                                     message=_("Password incorrect."),
                                     data=data)

            user.rotp = rotp
            user.save()

        #Handle the user attempting to delete their account
        elif data.form == "deleteaccount":
            if isinstance(data.passwd, unicode):
                data.passwd = data.passwd.encode('utf-8')

            #Make the user enter their username so they know what they're doing.
            if not user.username == data.username.lower():
                return 'json:', dict(success=False,
                                     message=_("Username incorrect."),
                                     data=data)

            #Check whether the user's supplied password is correct
            if not User.password.check(user.password, data.passwd):
                return 'json:', dict(success=False,
                                     message=_("Password incorrect."),
                                     data=data)

            #Make them type "delete" exactly
            if not data.confirm == "delete":
                return 'json:', dict(
                    success=False,
                    message=_(
                        "Delete was either misspelled or not lowercase."),
                    data=data)

            #Delete the user account and then deauthenticate the browser session
            log.info("User %s authorized the deletion of their account.", user)
            user.delete()
            deauthenticate()

            #Redirect user to the root of the server instead of the settings page
            return 'json:', dict(success=True, location="/")

        #Handle the user attempting to change the email address associated with their account
        elif data.form == "changeemail":
            if isinstance(data.passwd, unicode):
                data.passwd = data.passwd.encode('utf-8')

            #Check whether the user's supplied password is correct
            if not User.password.check(user.password, data.passwd):
                return 'json:', dict(success=False,
                                     message=_("Password incorrect."),
                                     data=data)

            #Check that the two provided email addresses match
            if not data.newEmail.lower() == data.newEmailConfirm.lower():
                return 'json:', dict(
                    success=False,
                    message=_("Provided email addresses do not match."),
                    data=data)

            #Make sure that the provided email address is a valid form for an email address
            v = EmailValidator()
            email = data.newEmail
            email, err = v.validate(email)
            if err:
                return 'json:', dict(
                    success=False,
                    message=_("Invalid email address provided."),
                    data=data)

            #Make sure that the new email address is not already taken
            count = User.objects.filter(**{
                "email": data.newEmail.lower()
            }).count()
            if not count == 0:
                return 'json:', dict(
                    success=False,
                    message=_("The email address provided is already taken."),
                    data=data)

            #Change the email address in the database and catch any email validation exceptions that mongo throws
            user.email = data.newEmail.lower()
            try:
                user.save()
            except ValidationError:
                return 'json:', dict(
                    success=False,
                    message=_("Invalid email address provided."),
                    data=data)
            except NotUniqueError:
                return 'json:', dict(
                    success=False,
                    message=_("The email address provided is already taken."),
                    data=data)

        #Handle the user attempting to merge 2 accounts together
        elif data.form == "mergeaccount":
            if isinstance(data.passwd, unicode):
                data.passwd = data.passwd.encode('utf-8')

            if isinstance(data.passwd2, unicode):
                data.passwd2 = data.passwd2.encode('utf-8')

            #Make the user enter their username so they know what they're doing.
            if user.username != data.username.lower(
            ) and user.username != data.username:
                return 'json:', dict(success=False,
                                     message=_("First username incorrect."),
                                     data=data)

            #Check whether the user's supplied password is correct
            if not User.password.check(user.password, data.passwd):
                return 'json:', dict(success=False,
                                     message=_("First password incorrect."),
                                     data=data)

            #Make sure the user isn't trying to merge their account into itself.
            if data.username.lower() == data.username2.lower():
                return 'json:', dict(
                    success=False,
                    message=_("You can't merge an account into itself."),
                    data=data)

            #Make the user enter the second username so we can get the User object they want merged in.
            if not User.objects(
                    username=data.username2.lower()) and not User.objects(
                        username=data.username2):
                return 'json:', dict(
                    success=False,
                    message=_("Unable to find user by second username."),
                    data=data)

            other = User.objects(username=data.username2).first()
            if not other:
                other = User.objects(username=data.username2.lower()).first()

            #Check whether the user's supplied password is correct
            if not User.password.check(other.password, data.passwd2):
                return 'json:', dict(success=False,
                                     message=_("Second password incorrect."),
                                     data=data)

            #Make them type "merge" exactly
            if data.confirm != "merge":
                return 'json:', dict(
                    success=False,
                    message=_("Merge was either misspelled or not lowercase."),
                    data=data)

            log.info("User %s merged account %s into %s.", user.username,
                     other.username, user.username)
            user.merge(other)

            #Redirect user to the root of the server instead of the settings page
            return 'json:', dict(success=True, location="/")

        else:
            return 'json:', dict(success=False,
                                 message=_("Form does not exist."),
                                 location="/")

        return 'json:', dict(success=True, location="/account/settings")
示例#48
0
def good_enough_password(form, field):
    if password_strength(field.data)['score'] < 4:
        msg = 'Get a better password'
        raise ValidationError(msg)
示例#49
0
def run(db, args):
    total, local_users, domain_users, computers = db.counts

    print("cracke-dit report for {}\n".format(args.domain))
    print("Local / Domain users:\t{}/{}".format(local_users, domain_users))

    if not args.only_enabled:
        print("Enabled / disabled users:\t{}/{}".format(*db.user_counts))

    if not args.only_users:
        print("Computer accounts:\t{}\t{:.2f}%".format(
            computers, (computers / total) * 100))

    cracked, blank, historic = db.password_stats
    print("Passwords cracked:\t{}/{}\t{:.2f}%".format(cracked, total,
                                                      (cracked / total) * 100))
    print("Historic passwords:\t{}\t{:.2f}%".format(historic,
                                                    (historic / total) * 100))

    only_alpha, with_special = db.password_char_stats
    print("Only alphanumeric:\t{}\t{:.2f}%".format(only_alpha,
                                                   (only_alpha / total) * 100))
    print("With 'special char':\t{}\t{:.2f}%".format(
        with_special, (with_special / total) * 100))

    headers = ["Password", "Length", "Count", "Score", "Users"]
    fmt_lambda = lambda password, count, score, users: [
        password,
        len(password), count,
        __coloured_score(score),
        __process_users(users)
    ]

    take_top = 10
    top_passwords = db.get_top_passwords(
        sortby=lambda (password, count, score, users): count,
        reverse=True,
        limit=take_top)
    __print_table(title="Top {} Passwords (by use)".format(take_top),
                  headers=headers,
                  align=[">", "<", "<", "<", ""],
                  values=top_passwords,
                  format=fmt_lambda)

    take_top = 5
    bad_pass = db.get_top_passwords(
        sortby=lambda (password, count, score, users):
        (zxcvbn.password_strength(password)["score"], len(password)),
        reverse=False,
        limit=take_top)
    __print_table(title="Top {} Worst Passwords".format(take_top),
                  headers=headers,
                  align=[">", "<", "<", "<", ""],
                  values=bad_pass,
                  format=fmt_lambda)

    __graph_passwords_containing(
        "Months", db,
        OrderedDict([(calendar.month_name[m], 0) for m in range(1, 13)]))
    __graph_passwords_containing(
        "Days", db,
        OrderedDict([(calendar.day_name[d], 0) for d in range(0, 7)]))
示例#50
0
 def __call__(self, value):
     res = zxcvbn.password_strength(value)
     if res.get('entropy') < self.password_minimum_entropy:
         raise ValidationError(self.message % _("Password is too weak"), code=self.code)
示例#51
0
def initiate_with_a_trie_file():
    # so we should only have a list of names + typos

    file_path = MAIN_DIR + 'rockyou-ascii.txt'  # for quick checks
    # file_path = MAIN_DIR + 'rockyou-ascii_3.txt' ##

    print "Starting to create the trie"
    # list_for_marisa = []
    # with open(TRIE_PATH,'rb') as trie_file:
    # 	for line in trie_file:
    # 		tup = line.split()
    # 		code = ' '.join(tup[1:])
    # 		# print "code:{}, code length:{}".format(code,len(code)) # TODO REMOVE
    # 		list_for_marisa.append(code)
    # TRIE_ALL = marisa_trie.Trie(list_for_marisa) # TODO CHANGE TO READ FROM FILE

    another_trie_path = MAIN_DIR + 'myTrieYay.txt'
    TRIE_ALL = marisa_trie.Trie()
    TRIE_ALL.load(another_trie_path)
    print "loaded the marisa_trie"
    # print "Trie created with length: {}".format(len(list_for_marisa))
    #
    # NUM_OF_LINES = 10**8 # TODO CHANGE # TRIE SIZE
    NUM_OF_LINES = 265796
    MAX_LENGTH = (15 * 2) + 1

    UTF8 = 'utf-8'
    # .dcode(UTF8)
    UNINIT = -1.0
    DEF_LINE = [UNINIT] * MAX_LENGTH
    pw_arr = np.array([DEF_LINE] * NUM_OF_LINES)
    typo_arr = np.array([DEF_LINE] * NUM_OF_LINES)

    SUM_ALL = 1000  # TODO CHANGE according to check

    print "Starting to read from file and collect the data"
    with open(file_path, 'rb') as ff:
        # at the end of the file the format is broken. simply deleted it manually
        START = time()
        print("start:{}".format(START))
        #for line in all_data: #
        count_fails = 0
        for line in ff:
            #try:
            tup = (line.split())
            count = int(tup[0])
            pw_pp = float(count) / SUM_ALL
            splitted_str = [x for x in tup[1:]]
            pw = ' '.join(splitted_str)
            pw_ent_bits = password_strength(pw)['entropy']
            pw_id = TRIE_ALL.key_id(pw.decode(UTF8))
            typos = get_pos_typos(pw, pw_ent_bits, 1, NNN)
            typos_with_id = [(TRIE_ALL.key_id(tt.decode(UTF8)), pp)
                             for (tt, pp) in typos]
            # writing for pw
            pw_arr[pw_id][0] = pw_pp
            index_in_pw_arr = 1
            for tt_id, pp in typos_with_id:
                try:
                    # updating pw_array
                    pw_arr[pw_id][index_in_pw_arr] = tt_id
                    pw_arr[pw_id][
                        index_in_pw_arr +
                        1] = pp  ## this is the probability of having this typo in cache from that pw
                    index_in_pw_arr += 2

                    # updating typo_arr
                    rel_typo_pp = pp * pw_pp  # the typo gain probabily based in the pw's prob as well
                    old_typo_pp = typo_arr[tt_id][0]
                    if old_typo_pp == UNINIT:  # AKA un initiated
                        typo_arr[tt_id][0] = rel_typo_pp
                    else:
                        typo_arr[tt_id][0] += rel_typo_pp

                    index_in_typo_arr = 1
                    # will raise error if out of length
                    while index_in_typo_arr != UNINIT:  # skipping filled
                        index_in_typo_arr += 2  #
                    typo_arr[tt_id][index_in_typo_arr] = pw_id
                    typo_arr[tt_id][index_in_typo_arr + 1] = pp

                except IndexError as e:
                    print "reached indexError: pw_I={}, typo_I:{}".format(
                        index_in_pw_arr, index_in_typo_arr)

                # adding for thse typos

            # except Exception as e:
            # 	count_fails += 1
            # 	print "failed on something. count={}".format(count_fails)
            # 	raise e

    print "Finished aggregating the data"
    print "Starting to calculate attacks"
    # out of open file, still in def
    # calculating the ATTACK
    QUERIES = 1000
    while QUERIES:
        # find max
        max_score = 0
        max_typo_id = 0
        for typo_id in xrange(NUM_OF_LINES):
            t_p_sum = typo_arr[typo_id][0]
            max_typo_id = typo_id if (t_p_sum != UNINIT
                                      and t_p_sum > max_score) else max_typo_id

        # found max
        added_p = typo_arr[max_typo_id][0]
        print "\n" * 2, "*" * 20  # TODO REMOVE
        print "chose {},({}) with {} users".format(
            max_typo_id, TRIE_ALL.restore_key(max_typo_id), added_p)
        broken += added_p
        # removing chosen
        typo_arr[max_typo_id][
            0] = 0  # TODO CHANGE? the easiest way to remove it
        # need to also remove from other pw's
        for index_in_typo_line in xrange(
                1, MAX_LENGTH, 2):  # 2 adjasant indexes are used each time
            # if reached the end of initiated cells:
            if typo_arr[typo_id][index_in_typo_line] == UNINIT:
                break
            pw_id = typo_arr[typo_id][index_in_typo_line]
            pp_of_chosen_typo_for_pw = typo_arr[typo_id][index_in_typo_line +
                                                         1]
            print "pw_id:{}, count: {}".format(pw_id, count)  # TODO REMOVE
            try:
                # calc new prob of pw
                # update the prob of all the other typos of that pw

                # gaining the prob of chosen typo accuring for that pw

                old_pw_pp = pw_arr[pw_id][0]
                new_pw_pp = old_pw_pp * (1 - pp_of_chosen_typo_for_pw)
                pw_arr[pw_id][0] = new_pw_pp
                # updating in case it's a typo as well # TODO CHECK _ I think we entered all pws into typo_arr
                typo_arr[pw_id][0] -= (old_pw_pp - new_pw_pp)

                sum_of_rest_typos_pp = 0
                for index_in_pw_arr in xrange(1, MAX_LENGTH, 2):
                    if index_in_pw_arr == UNINIT:
                        break
                    sum_of_rest_typos_pp += pw_arr[pw_id][index_in_pw_arr + 1]
                assert sum_of_rest_typos_pp and sum_of_rest_typos_pp < 1  # TODO CHANGE - should be zero otherwise we wouldn't have reached that typo
                # re-normalizing the pp of the pw's typos
                for index_in_pw_arr in xrange(1, MAX_LENGTH, 2):
                    if index_in_pw_arr == UNINIT:
                        break
                    tt_id = pw_arr[pw_id][index_in_pw_arr]
                    old_tt_pp = pw_arr[pw_id][index_in_pw_arr + 1]
                    new_tt_pp = old_tt_pp / sum_of_rest_typos_pp
                    pw_arr[pw_id][index_in_pw_arr + 1] = new_tt_pp
                    # finding the pw's index in the typo's row (in typo_arr)
                    pw_index_in_typo_arr = 1
                    while typo_arr[tt_id][pw_index_in_typo_arr] != pw_id:
                        pw_index_in_typo_arr += 2
                    # should be found - so not checking bounds
                    typo_arr[tt_id][0] -= (old_tt_pp - new_tt_pp)
                    typo_arr[tt_id][pw_index_in_typo_arr + 1] = new_tt_pp

            except TypeError as e:  # TODO REMOVE
                print "bummer"
                raise e

        QUERIES -= 1
    print "BROKEN %: {}".format(broken)
示例#52
0
 def __call__(self, value):
     res = zxcvbn.password_strength(value)
     if res.get('entropy') < PASSWORD_MIN_ENTROPY:
         raise ValidationError(self.message % _("Password is too weak"),
                               code=self.code)