I'm working on a some kind of password generated some sort of program, using the
itertools
module of the python, with itsproduct
function i'm trying to generate unique passwords that are NOT already saved in the database i'm having.
The problem is:
When i'm trying to generate more passwords, i need to wait a hell of a time! for the new password to come out, i've already written the code to filter the passwords that are already within the database BUT the product
function STILL processes the passwords EVEN if they are already used, then it prints out the passwords that aren't used already which still takes the same amount of time which is just too much!
Now i know that i could use my GPU for this process, but i'm sure there's gotta be a logical operation to stop this function from generating the already used passwords.
Here's the source code
(don't pay too much attention to the other parts of the code, i know it doesn't work by itself because i'm using this Generator
function in another kind of master main program):
from string import *
from itertools import product
# The password generator function.
# a little detail about the parameters:
# From = password starts from how many characters
# To = password ends with how many characters
# Fname = stands for 'file name' which is actually the database name
# cn, Base = these are just to organize different databases, not too much important in this case
def Generator(From, To, Fname, cn, Base):
# Defining the database
global db
db = Fname+cn+'.txt'
# Listing all the already used passwords in the 'lines' list
global lines
lines = []
mainDB = open(Fname+str(Base)+'.txt')
lines = mainDB.readlines()
mainDB.close()
# Defining the characters which (probably) can't be used as passwords(due to injection attacks and so on...)
Blocked = ",:?/\\|<>*"+"'"+'"'
# The ones that i'm not sure if they have to be blocked... but i'm blocking them anyway :|
proBlocked = ";[]{}()+=^`"
Blocked += proBlocked
chars = ascii_letters + digits + punctuation
# Deleting all the blocked characters from the main 'chars' string
for c in Blocked:
chars = chars.replace(c,'')
# Going for generating the password trying every single password we can make and take a unique one out for use
for i in range(From,To):
# Starting the `product` module which is the main element of the program
for j in product(chars, repeat=i):
# Defining the 'word' container(or the 'password' container if you will)
global word
# Putting the generated word in the container(variable)
word = "".join(j)
# Opening the database
p = open(db, '+r')
# Checking if the password has already been used and added to the main database
if not(word in str(lines)):
# Adding to the database and returning the unique password
p.write(p.read() + word + '\n')
p.close()
return word
Here's the main program:
from Generator import Generator
import os
import sys
# This part needs some more work, like designing and so on
# right now we're just testing.
while True:
os.system('cls')
inp = input("Type 1 to start generating, or type 0 to close the program:\n")
if inp.isdigit():
if inp == '1':
break
elif inp == '0':
sys.exit()
print("Here's your unique password: "+Generator(4, 10, "MainDB", 1, 1))
This is how the program's output looks like:
Type 1 to start generating, or type 0 to close the program:
1
Here's your unique password: aaaa
Now by filtering more passwords within the database, the passwords wouldn't be things like 'aaaa' and they'll be nicer and sometimes mean something and can be remembered (instead of using random though cause i already have a program for that one)
Really appreciate your help <3 again, the problem is: i'm looking for a way to filter the already used password IN the product module ITSELF to stop those from being EVEN generated to save a lot of time.
Thanks in advance!
"Filtering out the already used passwords" really comes down to checking the output of the product
function against some set of used passwords. (Even if you wrote your own special "product_with_exclusions" function, it would need to work that way.)
Your code already does this checking, but it can be made faster. On every iteration of the loop over the results of product
, your code in the question turns the list of passwords into a string and checks the output against that. Repeatedly converting list -> str and checking whether the password is part of that big string is slow. It's better to (1) not do the conversion to str, (2) instead of a list
, use a set
(it's much quicker to check whether a value is in a large set, compared to the same-size list).
With that, the optimised code could look something like this. (This includes a few other tidyups - removed unnecessary globals, used with-blocks when opening files, and wrote the new password in append mode.)
from string import *
from itertools import product
# The password generator function.
# a little detail about the parameters:
# From = password starts from how many characters
# To = password ends with how many characters
# Fname = stands for 'file name' which is actually the database name
# cn, Base = these are just to organize different databases, not too much important in this case
def Generator(From, To, Fname, cn, Base):
# Defining the database
db = Fname+cn+'.txt'
# Listing all the already used passwords in the 'lines_set' set for fast lookup
with open(Fname+str(Base)+'.txt') as mainDB:
lines_set = {l.strip() for l in mainDB.readlines()}
# Defining the characters which (probably) can't be used as passwords(due to injection attacks and so on...)
Blocked = ",:?/\\|<>*"+"'"+'"'
# The ones that i'm not sure if they have to be blocked... but i'm blocking them anyway :|
proBlocked = ";[]{}()+=^`"
Blocked += proBlocked
chars = ascii_letters + digits + punctuation
# Deleting all the blocked characters from the main 'chars' string
chars = [c for c in chars if c not in Blocked]
# Going for generating the password trying every single password we can make and take a unique one out for use
for i in range(From,To):
# Starting the `product` module which is the main element of the program
for j in product(chars, repeat=i):
# Putting the generated word in the container(variable)
word = "".join(j)
# Checking if the password has already been used and added to the main database
if word not in lines_set:
# Adding to the database and returning the unique password
with open(db, 'a') as p: # Open in append mode so we just write one new line
p.write(word + '\n')
return word