I'm a beginner in Python and my assignment is to guess the password by running through the length of the unknown, random password and then replacing that position with the correct letter/number. I know it involves running the code until a match is found but I'm stuck.
You are to write a program that will try to guess each position of the password. The program must use a function that contains the code to hack the password.
Use of lists and methods/functions such as list( ) and .join will be helpful.
You should begin by displaying a string made up of asterisks (e.g. *******) equal to the length of the generated password.
As you match each letter/number in the secret password, replace the asterisk in that same position with that letter/number.
The output should look like this:
Password is yfdszk
Hacking...
Found match at position 2
*d****
Found match at position 1
*fd***
Found match at position 5
*fd**k
Found match at position 3
*fds*k
Found match at position 0
yfds*k
Found match at position 4
yfdszk
I did it! yfdszk
Here is my code:
import random
characters="abcdefghijklmnopqrstuvwxyz0123456789"
charList=list(characters)
def generatePassword(pwLen):
pw=""
for i in range(pwLen):
rand=int(random.randint(0,len(charList)-1))
pw=pw + (charList[rand])
pwList = list(pw)
return pw
def hackPassword(pw):
r`enter code here`and=int(random.randint(0,len(charList)-1))
pw=pw + (charList[rand])
pwList = list(pw)
asterisk = "*" * len(pw)
asteriskList = list(asterisk)
print asterisk
for numbers in range(len(charList)):
if charList == pwList[]:
password = pw[:index] + "*" + pw[index+1:]
password=generatePassword(8)
# display secret
print "Password is " + password
hackPassword(password)
I need to be able to guess the password, using a for loop to go through the length of the password, then finding a match, and then replacing that asterisk with the found letter/number.
But I'm getting this error message:
IndexError: list index out of range on line 20
Although your sample run is flawed, I believe I understand the gist of what you're trying to do. You generate a random password and then represent it with asterisks, so that the length is shown. Then, for each character in characters="abcdefghijklmnopqrstuvwxyz0123456789" you check if it matches any of the chars in the password. By the time you've run through it, you're done. So, you're going to need a double nested loop. I won't write it for you, but i'll give you a hint, in pseudocode:
generate a random password
make a corresponding 'fake' password of the same length of asterisks
for char in charList:
for position in actual password:
if char matches that position:
change the asterisk to that char in the fake password
if my fake password is cracked (no more asterisks):
print('Whoohoo!')
go home, you're done
Hope this helps! Getting the logic right is always the hardest part of programming!
As a side note, I got the above understanding because I noticed in your example that you are cracking the password in alphabetical order... d-f-k-s-y-z...
Related
I trying to make a password generator using python. Currently, I just want the program to print random characters from the ascii table. I will later introduce numbers and symbols. I used a for loop to print random character from a range that the user inputs. It works however, when I use the end='' to print the characters on the same line a % shows up. I think it is there to show that it printed a no character. I would like the program to not print the % because later I will add other numbers and symbols.
I tried subtracting 1 from the range of number. What resulted was the same string with a % but 1 less than intended. I also tried creating a while loop that would print while the variable was less than the password number. It also printed the %.
Here is the code:
import random
import string
letters=string.ascii_letters
passwordnumber=int(input("How many characters do you want your password to be? "))
for i in range(passwordnumber):
print(random.choice(letters), end='')
The % print by your shell (may be zsh), it means the string not end by "\n". It's just a reminder from the shell. There is nothing wrong with you. You can just add a print() in the end of your code to print a "\n", and % will not show again.
Try this
characters = list(string.ascii_letters + string.digits + "!##$%^&*()")
def generate_random_password():
## length of password from the user
length = 8
## shuffling the characters
random.shuffle(characters)
## picking random characters from the list
password = []
for i in range(length):
password.append(random.choice(characters))
## shuffling the resultant password
random.shuffle(password)
## converting the list to string
## printing the list
return "".join(password)
Your script works absolutly fine in my side. see this https://onlinegdb.com/9EagkKVW1
If you feel like it's issue with end you can simply concat outputs to string and print at once like so.
import random
import string
letters=string.ascii_letters
pas =''
passwordnumber=int(input("How many characters do you want your password to be? "))
for i in range(passwordnumber):
pas += random.choice(letters)
print(pas)
outputs #
How many characters do you want your password to be? 5
AvfYm
we can use the random .sample() method. it requires 2 arguments:
- iterable of elements to use
- number of elements to take
the result does not contain duplicates.
import random
import string
letters=string.ascii_letters
passwordnumber=int(input("How many characters do you want your password to be? "))
pas = ''.join(random.sample(letters, k=passwordnumber))
print(pas)
What im making
Hi!
Im making a password generator script in Python ( Script below ). and i was wondering what the best way would be to make sure the passwords dont have two of the same character/symbol right after eachother.
as an example:
kjhd8!3JJp-#huwwg
i would like a way within my script to make sure the duplicates arent "touching". if that makes sense (my english isnt very good).
the same password can have the same character, thats fine. but i would like it not to have them "touching"
like:
kjwhd8!3Jp-#huwJg
if that makes sense.
The script
import random
import string
import sys
#amount of passwords to make
amount = 10
# Characters and symbols to use for the password
# ive split it up to make sure it takes from all of the lists
chars ="abcdefghjkmnpqrstuvwxyzABCDEFGHJK"
specials="#####!-----"
digits="2346789"
characters = list(chars + digits + specials)
def generate_random_password():
# length of the passwords
length = 18
# mixes and shuffles the characters
random.shuffle(characters)
# Puts the sections together at random
password = []
for i in range(length):
password.append(random.choice(characters) )
# another shuffle to make sure (probably noy needed but meh)
random.shuffle(password)
# converts to a string
print("".join(password))
# Prints out as many passswords as stated in the "amount" variable
for index in range(amount):
generate_random_password()
You can just check if the generated char is the same that the previous one, if it is: pick another char, else continue.
prev_char=None
for i in range(length):
random_char = random.choice(characters)
while prev_char == random_char:
random_char = random.choice(characters)
password.append(random_char)
prev_char = random_char
You can use a regex for this!
The expression:
(.)\1
What it does:
(.) - group that matches one character
\1 - reference to group 1 (the group above)
What this essentially does is that it looks for a character repeating right after itself.
How to use it?
import re
any(re.findall(r"(.)\1", "kjwhd8!3Jp-#huwJg"))
findall will find any ocurrences of this; any will give you True or False if there are any cases.
Note: You could also extend this so that the same character doesn't repeat within the next let's say 4 characters: (.).{0,4}\1
This question already has answers here:
Validation of a Password - Python
(14 answers)
Closed 1 year ago.
I would like to test if the input value meets the criterias:
at least one lower case letter
at least one upper case letter
at least one digit
at least one character that is non \w
It seems the regex I programmed only follows this specific order like:
abCD99$%
But if I shuffled the sequence, the regex doesn't work anymore:
CD99ab$%
Anyone knows what the problem is please? Cheers in advance.
import re
# Asks user for an input
print('Please enter a password for checking its strength:')
pwd = input('> ')
#Test the input to see if it is more than 8 characters
if not len(pwd) < 8:
pwdRegex = re.compile(r'([a-z]+)([A-Z]+)([0-9]+)(\W+)') #order problem
if not pwdRegex.search(pwd) == None:
print('Password OK.')
else:
print('Please make sure password fulfills requirements!')
else:
print('Characters must not be less than 8 characters!')
You need to make use of lookaheads to verify your requirements:
(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*\W)^.+$
(?=.*[a-z]) - make sure we have a lowercase char somewhere
(?=.*[A-Z]) - make sure we have an uppercase char somewhere
(?=.*[0-9]) - make sure we have a digit somewhere
(?=.*\W) - make sure we have a non-\w somewhere
^.+$ - all the aforementioned requirements were met so lets capture the entire line
This piece can be omitted if you're just doing a pass/fail test and don't need to capture anything
https://regex101.com/r/HdfVXp/1/
In your case, I think it could be a good solution to make your validation without regex:
def isGoodPassword(password):
# contains upper and lower, digit and special char
return (not password.islower()
and not password.isupper()
and any(c.isdigit() for c in password)
and any(not c.isalnum() for c in password))
isGoodPassword('hello') # False
isGoodPassword('Hello!') # False
isGoodPassword('Hello!1') # True
The https://pypi.org/project/password-strength/ package contains code to do this. If you are interested in how this is done rather than actually doing it you could read the source code.
I am brand new to Python.
I'm trying to ensure a username contains ONLY alpha characters (only a-z). I have the below code. If I type digits only (e.g. 7777) it correctly throws the error. If I type numbers and letters mix, but I START with a number, it also rejects. But if I start with a letter (a-z) and then have numbers in the string as well, it accepts it as correct. Why?
def register():
uf = open("user.txt","r")
un = re.compile(r'[a-z]')
up = re.compile(r'[a-zA-Z0-9()$%_/.]*$')
print("Register new user:\n")
new_user = input("Please enter a username:\n-->")
if len(new_user) > 10:
print("That username is too long. Max 10 characters please.\n")
register()
#elif not un.match(new_user):
elif not re.match('[a-z]',new_user):
print("That username is invalid. Only letters allowed, no numbers or special characters.\n")
register()
else:
print(f"Thanks {new_user}")
Why don't you use isalpha()?
string = '333'
print(string.isalpha()) # False
string = 'a33'
print(string.isalpha()) # False
string = 'aWWff'
print(string.isalpha()) # True
in your code, uf, un and up are unused variables.
the only point where you validate something is the line elif not re.match('[a-z]',new_user):, and you just check if there is at least one lowercase char.
To ensure that a variable contains only letters, use: elif not re.match('^[a-zA-Z]{1,10}$',new_user):
in the regex ^[a-zA-Z]{1,10}$ you find:
^ : looks for the start of the line
[a-zA-Z] : looks for chars between a and z and between A and Z
{1,10} : ensure that the char specified before (letter) is repeated between 1 and 10 times. As LhasaDad is suggesting in the comments, you may want to increase the minimum number of characters, e.g. to 4: {4,10}. We don't know what this username is for, but 1 char seems in any case too low.
$ : search for the end of the line
Since you were looking for a RegEx, I've produced and explained one, but Guy's answer is more pythonic.
IMPORTANT:
You're not asking for this, but you may encounter an error you're not expecting: since you're calling a function inside itself, you have a recursive function. If the user provides too many times (more than 1000) the wrong username, you'll receive a RecursionError
As the re.match docs say:
If zero or more characters at the beginning of string match the regular expression pattern, return a corresponding match object.
That's exactly what's happening in your case: a letter in the beginning of the string will satisfy the match. Try the expression [a-z]+$ which will make sure that the match expands till the end of the string.
You can check the length on the same go: [a-z]{1,10}$.
I writing a password generator and I ran into this annoying issue, and it is the repeating a a number or letter on the same line. The user gives the program a format on how they want their password to be generated ex "C##d%%%"
where # is only letters and where % is only numbers, and the user also inputs the numbers and letters to generate the password, then the program is suppose to print out something like cold123, but instead it prints out cood111 or clld111, I will post a snippet of my code below, but please don't bad mouth it, I'm fairly new to python, self-taught and just about couple of months into the python experience.
class G()
.
.
.
# self.forms is the format the user input they can input things such as C##d%%%
# where # is only letters and where % is only numbers
# self.Bank is a list where generated things go
AlphaB = [] #list Of All Of The Positions That have The # sign in The self.forms
NumB = [] #list of All of the positions that have a % sign
for char in self.forms:
if char == '#':
EOL=(self.Position) # Positions End Of Line
Loc = self.forms[EOL] # Letter
AlphaB.append(EOL)
if char == '%':
EOL=(self.Position)
Loc = self.forms[EOL]
NumB.append(EOL)
self.Position+=1 # Move right a position
for pos in AlphaB:
for letter in self.alphas: #letters in The User Inputs
GenPass=(self.forms.replace(self.forms[pos],letter))
#Not Fully Formatted yet, because Only The letter been formatted
if GenPass.find('%'):
for Pos in NumB:
for number in self.ints:
GenPass=(GenPass.replace(GenPass[Pos],number))
if GenPass not in self.Bank:
#Cood111
print (GenPass)
self.Bank.append(GenPass)
else:
if GenPass not in self.Bank:
print (GenPass)
self.Bank.append(GenPass)
GenPass.replace(GenPass[Pos],number) will replace every occurrence of the character at GenPass[Pos] with the value of number. You need to make sure you replace one character at a time.
Create a list of all chars and a list with all nums, then just pick one by using list.pop(randint(0, len(list) - 1), you will always pick a different letter / number like this but you will also be limited to 10 digits (0-9) and 20-something letters.