Beastly Gerbil
Beastly Gerbil

Reputation: 225

Password Checker

I have created a password checker which generates a random character and compares it until all the characters are the same. But as it rolls through it repeats the character multiple times. Is there a way of making it so the character doesn't repeat, possibly putting the characters into a list? I could then use the

list.del()

function to stop it repeating. Here is my code:

import string
import random
import time
print('Welcome to the password checker')
characters = string.ascii_lowercase + string.digits + string.ascii_uppercase + ' .,!?;:`"+/*()@#$&_-='

password = input("Enter your password: ")
tryFirst = ''.join(random.choice(characters) for i in range(len(password)))
trySecond = ''

Finished = False

attempt = 0
while Finished == False:
    print("{}) {}".format(attempt,tryFirst))
    trySecond = ''
    Finished = True
    for num in range(len(password)):
        if tryFirst[num] != password[num]:
            Finished = False
            trySecond += random.choice(characters)
        else:
            trySecond += password[num]
    attempt += 1
    tryFirst = trySecond
    time.sleep(0.05)
print("Password found! That took {} attempts".format(attempt))
if attempt < 100:
    print("Your password isn't safe")
elif attempt < 250:
    print("Your password is quite safe, could do with improvement")
elif attempt < 400:
    print("Your password is adequately safe")
elif attempt < 600:
    print("Your pasword is safe")

Upvotes: 0

Views: 862

Answers (1)

Tom Gijselinck
Tom Gijselinck

Reputation: 2498

Quick Answer

First, as others already have mentioned, your method will not give you the answer you seek. For example, inputting example as a first password and Qm2cl?X as a second. Your program would return a similar result although they are obviously not equally strong passwords. The first can be found in a dictionary while the second is much harder to guess (it possesses more randomness).

To answer your question, you could use the same random character for all positions in your word each iteration. Then you can safely pop each checked character off the characters list. Here is a possible implementation:

import string
import random
import time

print('Welcome to the password checker')
characters = string.ascii_lowercase + string.digits + string.ascii_uppercase + \
             ' .,!?;:`"+/*()@#$&_-='
characters = list(characters)
random.shuffle(characters)

password = input("Enter your password: ")
tryFirst = characters.pop() * len(password)

Finished = False

attempt = 0
while not Finished:
    print("{}) {}".format(attempt, tryFirst))
    trySecond = ''
    Finished = True
    try:
        char = characters.pop()
    except IndexError:
        print 'No more characters to check'
    for num in range(len(password)):
        if tryFirst[num] != password[num]:
            Finished = False
            trySecond += char
        else:
            trySecond += password[num]
    attempt += 1
    tryFirst = trySecond
    time.sleep(0.05)
print("Password found! That took {} attempts".format(attempt))
if attempt < 100:
    print("Your password isn't safe")
elif attempt < 250:
    print("Your password is quite safe, could do with improvement")
elif attempt < 400:
    print("Your password is adequately safe")
elif attempt < 600:
    print("Your password is safe")

Fundamental Problem

A problem however is that you check each character individually, which would be impossible to do for a real hacker. By doing this, you reduce the problem difficulty of finding the correct password significantly. For example, in your case you have 83 different characters in your characters list. By checking each character individually, you will never need more than 83 attempts to get the correct password (if you remove your duplicates problem). If you would only be able to check a complete password instead of characters individually, as would be the case in a live situation, the number of attempts to find the correct password is much higher, being 83^password_length/2. For example, you would already need 3444 attempts on average to guess a password of two characters and 285893 for a password of three characters.

So, if you would really like to know the number of attempts a primitive brute-force algorithm would need to guess a given password composed of the 83 characters in your characters list, just use this formula: 83^password_length/2.

But be warned that this does not take into account that humans tend to pick passwords with a certain structure and thus with a certain predictability. Password cracking programs exploit this weakness by using for example dictionary attacks and rainbow tables. Thus the actual number of attempts a cracking program would need may be much lower than this formula would suggest.

Upvotes: 2

Related Questions