Python: Removing duplicate strings and staying within certain parameters - python

Currently, I am designing a credential database meant to hold a servername, username, and password in a text file. However, for the servername and passwords I am trying to make them unique (no two credentials / logins can have the same servername AND password, usernames can be duplicated).
For example,
# This is NOT acceptable because the servername is duplicated.
servername : username : password
google : john : 123
google : john : 321
# This is acceptable because the servername and password are unique.
servername : username : password
google : john : 123
yahoo : john : 321
I have searched stackoverflow for some answers but I was not able to find exactly what I am looking for. In my program's current state, when credentials are entered, they are simply listed right underneath the existing one and continue to add each additional credential without checking for duplicates.
# Creates the file "passdatabase.txt" for use with this code.
with open('passdatabase.txt', 'a+') as searchfile:
searchfile.close()
# Here I initialize the variable / count for the while loop
x = 1
print("\n======================="+
"\nYou chose to add a credential."
"\n-----------------------")
# User enters in a server name to be saved.
addservername = input("Server Name: ")
# User enters in a username to be saved.
addusername = input("Username: ")
# User enters in a password to be saved.
addpassword = input("Password: ")
# All inputs are combined to create a single variable in the format (servername : username : password)
addCredential = addservername + " : " + addusername + " : " + addpassword
# Loops until the user enters a valid submission (either [y] or [n]) to confirm information.
while x == 1:
# Input information is displayed for user to confirm.
confirmCredential = input("~~~~~~~~~~~~~~~~~~~~~~~" +
"\nPlease verify the entered credentials.\n" +
"\nServer Name: [" +
addservername + "]" +
"\nUsername: [" +
addusername + "]" +
"\nPassword: [" +
addpassword + "]" +
"\n\nIs the information correct? (y/n): ")
print("~~~~~~~~~~~~~~~~~~~~~~~")
if confirmCredential == "y":
x = 2
with open('passdatabase.txt', 'r') as searchfile:
lines_seen = set(open('passdatabase.txt'))
for addCredential in (searchfile, 1):
if addCredential not in lines_seen:
with open('passdatabase.txt', 'a+') as searchfile:
# I set the format of the credential to save in the text file as
# servername : username : password.
searchfile.write("\n" + addservername + " : " + addusername + " : " + addpassword)
print("[!] SUCCESS! Your credentials have successfully been stored [!]" +
"\n=======================")
# This breaks the for loop so it does not continue the code.
break
else:
print('Duplicate credential detected!')
elif confirmCredential == "n":
x = 2
print("[!] Your credentials have not been stored [!]" +
"\n=======================")
else:
print("###########################################################" +
"\n[!!!ERROR!!!] PLEASE ENTER EITHER [y] OR [n]. [!!!ERROR!!!]\n" +
"###########################################################")
My questions / requests in one simple list are as follows:
- How do I ensure that the user can only enter in unique entries for their servername and password credentials while allowing duplicate username entries?
- If a duplicate is detected, I would like the code to stop from going further and ask the user for input again until a proper unique credential is provided.
- Should I be using a set or an array? (Data-order does not matter)
- I've seen quite a few duplicate checking scripts that involve the use of 2 .txt files, is this possible with only 1?
- In the future I plan on adding encryption to the password entries, password strength checker, and possibly a credential log (of who has logged in).
- Any input is welcome as I am always willing to learn!
I am fairly new to Python coding and I would really just like some guidance on what I should be looking into next, I'm honestly not sure if I am even headed in the right direction.
Thanks

Maybe you should use sqlite instead of pure text file.
If you really want to implement database feature in a txt file:
Use set for tuple(servername, password), check if exist before appending to file. Remember to load all exist ones from your txt file before ask user to input.
You'd better use a file lock to make sure that only one instance of your script run at the same time.

Related

How do I break an inner for loop every time a condition is satisfied?

Good afternoon,
Im very new to python coding and Im trying to write a very basic md5 brute force password cracker for a school project.
I am supposed to write a script that will crack a series of MD5 hashed passwords. The passwords must be read in from a text file named “hashes.txt”, with one password on every line. The script should then start generating passwords, starting with single character, and then two characters, etc
My thought process of how to make a brute force cracker is as follows:
import hashlib
import itertools
abc = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#0123456789"
abc_list = list(abc)
def combo():
md5_hash = ""
file_name = open("hashes.txt", "r")
for password in file_name:
password = password.strip()
#print(password)
for r in range(len(abc_list)):
combinations_object = itertools.combinations(abc_list, r)
combinations_list = list(combinations_object)
#print(combinations_list)
for lis in combinations_list:
glue = "".join(lis)
hash_object = hashlib.md5(glue.encode())
md5_hash = hash_object.hexdigest()
print(glue)
#print(md5_hash)
#print(glue + " " + md5_hash)
if md5_hash == password :
print("Your password is: " + "'" + glue +"' "+ md5_hash)
break
The passwords I am given to crack are:
Z,
AD,
God,
1234,
AbCdE,
Trojan
Every time I run the script it only outputs the password: Z and then runs through the rest without fulfilling the 'if' statement.
I have tried using the 'break' statement under the 'if' but the outcome is the same.
You might benefit from creating and storing the combinations list once (or rather, a generator).
https://stackoverflow.com/a/31474532/11170573
import itertools
def all_combinations(any_list):
return itertools.chain.from_iterable(
itertools.combinations(any_list, i + 1)
for i in range(len(any_list)))
You can change the code as follows:
import hashlib
import itertools
abc = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#0123456789"
abc_list = list(abc)
combinations_object = all_combinations(abc_list)
def combo():
file_name = open("hashes.txt", "r")
for password in file_name:
password = password.strip()
for comb in combinations_object:
glue = "".join(comb)
hash_object = hashlib.md5(glue.encode())
md5_hash = hash_object.hexdigest()
if md5_hash == password :
print("Your password is: " + "'" + glue +"' "+ md5_hash)
break
When you use break, what you are saying is break the loop I'm currently in.
Notice that your condition is wrapped by three for loops, so it will only break the inner inner loop and keep going with the rest.
What you can do is what Jason Baker sugests in https://stackoverflow.com/a/438869/16627440.
Change that break to return md5_hash and call the function in your print.
if md5_hash == password :
return md5_hash
# Outside your function
print("Your password is: " + "'" + glue +"' "+ combo())

Encrypted string doesn't give same value as identical string python

I'm writing a password manager program, and I need to store an encrypted string in a file. (The "service" variable) When the user needs to retrieve the information, they enter the same string as before. When I encrypt the same string, I get a different output. I've checked multiple times, and the string is the same. Anyone know of a fix for this?
Code I'm using to encrypt and write to the file:
def new_account(service, username, password, filepath, key):
# Encrypting the account details #
encrypted_service = key.encrypt(bytes(service, "utf-8"))
encrypted_username = key.encrypt(bytes(username, "utf-8"))
encrypted_password = key.encrypt(bytes(password, "utf-8"))
encrypted_service = encrypted_service.decode("utf-8")
encrypted_username = encrypted_username.decode("utf-8")
encrypted_password = encrypted_password.decode("utf-8")
password_file = open(f"{filepath}\passwords.txt", "a")
password_file.close()
password_file = open(f"{filepath}\passwords.txt", "r")
password_file_content = password_file.read()
password_file.close()
password_file = open(f"{filepath}\passwords.txt", "a")
if f"{encrypted_service},{encrypted_username},{encrypted_password}" in password_file_content:
password_file.close()
return("The account already exists.")
else:
password_file.write(f"{encrypted_service},{encrypted_username},{encrypted_password}\n")
password_file.close()
return f"Account saved for {service.title()} with username {username} and password {password}."
Code I'm using to retrieve the information:
# The account retrieval function #
def get_account(service, filepath, key):
encrypted_service = key.encrypt(bytes(service, "utf-8"))
encrypted_service = encrypted_service.decode("utf-8")
password_file = open(f"{filepath}\passwords.txt")
lines = password_file.read().split("\n")
word = f"{encrypted_service}"
# Getting the line with the account details #
for i in lines:
index = lines.index(i)
myline = lines[index]
encrypted_account_content = myline.split(",")
print(encrypted_account_content)
print(f"service is: {encrypted_service}")
if encrypted_account_content.count(encrypted_service) != 0:
# Decrypting the account details #
username = encrypted_account_content[1]
decrypted_username = key.decrypt(bytes(username, "utf-8"))
decrypted_username = decrypted_username.decode("utf-8")
password = encrypted_account_content[2]
decrypted_password = key.decrypt(bytes(password, "utf-8"))
decrypted_password = decrypted_password.decode("utf-8")
return f"Service: {service.title()}\nUsername: {decrypted_username}\nPassword: {decrypted_password}"
else:
return "Account not found. Please try again."
Any proper encryption will use randomization, so that the result will always be different, and you won't be able to tell that the plaintext was the same. That's needed to achieve semantic security. In practice, initialization vectors and modes of operation like CBC or CTR are used. The cryptography library you're using does it out of the box (with CBC mode).
You will either have to store service as a plaintext, which shouldn't significantly reduce the overall security, or decrypt each service field in order to find the needed record.

Problem with concatenating strings/ getting value from file

I have been writing a program that saves passwords in hash form, but I am trying to get a value from within my file which stores a value for the salt. For some reason, it doesn't seem to work.
Here is my code:
hashpass = hashlib.sha256()
salt = ['hbjGVY0Kj07,kbjgvhjb,ZsGhnBi0lp]
for line in login:
usr = input()
pas = input()
log = line.split(',')
if usr in line:
x = line
salt_num = int(x[2])
setpass = str(pas + salt[salt_num])
hashpass.update(setpass.encode('utf-8'))
I have tried everything, but still no results when I concatenate the string, I just get the value of pas
Here is what I tried and it works. The code you have shared has some issue that I would request you to cross check with original code.
import hashlib
hashpass = hashlib.sha256()
salt = ['hbjGVY0Kj07','kbjgvhjb','ZsGhnBi0lp']
login = ["user,68a782faf939dfa370345934d255101926b7f59b3a65ab7db5b0bc6f78ec25e5,0"]
for line in login:
#print(line)
usr = input() # I input "user"
pas = input() # I input "qwerty"
log = line.split(',')
#print(log)
if usr in line:
x = log
salt_num = int(x[2])
setpass = str(pas + salt[salt_num])
print(setpass)
hashpass.update(setpass.encode('utf-8'))
OUTPUT --> qwertyhbjGVY0Kj07
Things I would suggest you to check:
All the items in list salt are in quotes, i.e., as string.
Login is a list of strings having elements with comma separated value, like I have created.
change x=line to x=log inside if condition.
I have fixed the issue, but am getting different errors when comparing the variable hashpass with log[1], when comparing my program claims that the password is wrong, here is the whole program for reference.
login = open('login.csv','r')
def logging():
atmptcount = 0
while atmptcount < 3:
usr = input('Please enter your username: ')
pas = input('Please enter your password: ')
hashpass = hashlib.sha256()
for line in login:
log = line.split(',')
if usr.upper() in line:
print(log[2])
salt_num = int(log[2])
setpass = str(pas + salt[salt_num])
hashpass.update(setpass.encode('utf-8'))
if usr == log[0] and hashpass.hexdigest() == log[1]:
print('correct')
return True
print(hashpass.hexdigest())
print(log[1])
atmptcount = atmptcount + 1
print('Sorry you have entered your details incorrectly, please try again')
login.seek(0)
print('Sorry, you have reached your maximum login attempts!')
return False
I have changed the variable names a bit but its the saem concept

Update Active Directory Password using ldap python

Basically trying to reset the user's password using LDAP python. I've gone through various posts here but no luck :(.
Tried using :
a) modify_s() - returns "No such object" every time. Tried with different user DN.
{'info': "0000208D: NameErr: DSID-0310020A, problem 2001 (NO_OBJECT), data 0, best match of:\n\t'DC=mydomain,DC=com'\n", 'matched': 'DC=mydomain,DC=com', 'desc': 'No such object'}
Here is the code Snippet:
def changePassword(userEmail, oldPassword, newPassword):
try:
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
ldap_client = ldap.initialize("ldap://127.0.01.1:389")
ldap_client.set_option(ldap.OPT_REFERRALS, 0)
ldap_client.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
ldap_client.set_option(ldap.OPT_X_TLS,ldap.OPT_X_TLS_DEMAND)
ldap_client.set_option( ldap.OPT_X_TLS_DEMAND, True )
ldap_client.set_option( ldap.OPT_DEBUG_LEVEL, 255 )
ldap_client.simple_bind_s(ADMIN_EMAIL, ADMIN_PASSWORD)
# Set AD password
#unicode_pass = unicode('\"' + newPassword + '\"', "iso-8859-1")
unicode_pass = newPassword
password_value = unicode_pass.encode("utf-16-le")
add_pass = [(ldap.MOD_REPLACE, 'unicodePwd', [password_value]),( ldap.MOD_REPLACE, 'unicodePwd', [password_value])]
# Replace password
try:
user_dn = 'CN=%s,DC=mydomain,DC=com' % username
ldap_client.modify_s(user_dn, add_pass)
print "Active Directory password for", username, \
"was set successfully!"
except ldap.LDAPError, e:
sys.stderr.write('Error setting AD password for: ' + username + '\n')
sys.stderr.write('Message: ' + str(e) + '\n')
ldap_client.unbind_s()
return 'SOME_PROBLEM'
ldap_client.unbind_s()
return 'AUTHENTICATED'
except ldap.INVALID_CREDENTIALS:
ldap_client.unbind()
return 'INVALID_CREDENTIALS'
except ldap.SERVER_DOWN:
return 'SERVER_UNAVAILABLE'
b) passwd(userEmail, oldPassword, newPassword). It gets executed well but password is not updated.
Need help in identifying the problem.
Reference Links:
Python+LDAP+SSL
python-ldap and Microsoft Active Directory: connect and delete user
how to set lockoutTime and password of a user of Active Directory
How can I change password for domain user(windows Active Directory) using Python?
https://groups.google.com/forum/#!topic/macromedia.coldfusion.security/Rq7xx15OeBs
http://www.grotan.com/ldap/python-ldap-samples.html#add
http://marcitland.blogspot.in/2011/02/python-active-directory-linux.html
https://snipt.net/Fotinakis/change-active-directory-password-via-ldap-modify-call/
I think below program helpful for you.. windows active directory use password attribute as unicode method
https://technet.microsoft.com/en-us/magazine/ff848710.aspx
import ldap
import ldap.modlist as modlist
import base64
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
l = ldap.initialize('ldaps://exam.local')
l.simple_bind_s('Administrator#exam.local', 'p#ssw0rd1')
dn="cn=map6,ou=Police,dc=exam,dc=local"
new_password='p#ssw0rd3'
unicode_pass = unicode('\"' + new_password + '\"', 'iso-8859-1')
print (unicode_pass)
password_value = unicode_pass.encode('utf-16-le')
add_pass = [(ldap.MOD_REPLACE, 'unicodePwd', [password_value])]
print (password_value)
l.modify_s(dn, add_pass)
l.modify_s(dn, add_pass)
l.unbind_s()
I had the very same issue and decided to ask on Server Fault. The answer I got helped me to figure out what was wrong in my code. To summarize, there is 2 diifferent methods to update an AD password: 1 for regular user updating his own password, and another 1 for administrator (or any account with sufficient access rights) resetting the password for another user.
Method 1: User update his own password
ad_server = "ldaps://ad.xxx_domain.com"
ad_dn = "CN={0},OU=Users,OU=AF,DC=xxx_domain,DC=com"
username = 'my_username'
old_pwd = 'the_old_pa55word'
new_pwd = 'the_new_pa55word'
cert = os.path.join('/path', "to", 'server_cert.cer')
# LDAP connection initialization
l = ldap.initialize(ad_server)
# Set LDAP protocol version used
l.protocol_version = ldap.VERSION3
# Force cert validation
l.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_DEMAND)
# Set path name of file containing all trusted CA certificates
l.set_option(ldap.OPT_X_TLS_CACERTFILE, cert)
# Force libldap to create a new SSL context (must be last TLS option!)
l.set_option(ldap.OPT_X_TLS_NEWCTX, 0)
# Bind
l.simple_bind_s(ad_dn.format(username), old_pwd)
# Now, perform the password update
oldpwd_utf16 = '"{0}"'.format(old_pwd).encode('utf-16-le')
newpwd_utf16 = '"{0}"'.format(new_pwd).encode('utf-16-le')
mod_list = [
(ldap.MOD_DELETE, "unicodePwd", oldpwd_utf16),
(ldap.MOD_ADD, "unicodePwd", newpwd_utf16),
]
l.modify_s(ad_dn.format(username), mod_list)
Method 2: Admin account update regular user's password
ad_server = "ldaps://ad.xxx_domain.com"
ad_dn = "CN={0},OU=Users,OU=AF,DC=xxx_domain,DC=com"
admin_username = "i_am_the_admin"
admin_password = "admin123"
username = 'my_username'
new_pwd = 'the_new_complicated_password'
cert = os.path.join('/path', "to", 'server_cert.cer')
# LDAP connection initialization
l = ldap.initialize(ad_server)
# Set LDAP protocol version used
l.protocol_version = ldap.VERSION3
# Force cert validation
l.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_DEMAND)
# Set path name of file containing all trusted CA certificates
l.set_option(ldap.OPT_X_TLS_CACERTFILE, cert)
# Force libldap to create a new SSL context (must be last TLS option!)
l.set_option(ldap.OPT_X_TLS_NEWCTX, 0)
# Bind (as admin user)
l.simple_bind_s(ad_dn.format(admin_username), admin_password)
# Now, perform the password update
newpwd_utf16 = '"{0}"'.format(new_pwd).encode('utf-16-le')
mod_list = [
(ldap.MOD_REPLACE, "unicodePwd", newpwd_utf16),
]
l.modify_s(ad_dn.format(username), mod_list)
Please note that the second method needs to Bind with a different account (with sufficient rights) but allows to set the new password without re-typing the old one.
From what I can see is that you user_dn is not correctly set. Double check and ensure you full DN actually exists in the Directory Server. Check your username variable is correctly parsed (No newline or tab characters) and the Base DN is verified.
sys.stderr.write('Error setting AD password for: ' + username + '\n')
sys.stderr.write('DN: ' + user_dn + '\n')
sys.stderr.write('Message: ' + str(e) + '\n')
The error message is pretty clear that AD cannot find the object (DN) it wishes to modify **(NO_OBJECT)
{'info': "0000208D: NameErr: DSID-0310020A, problem 2001 (NO_OBJECT),
data 0, best match of:\n\t'DC=mydomain,DC=com'\n", 'matched':
'DC=mydomain,DC=com', 'desc': 'No such object'}

Flask Google Maps Infobox with multiple marker images leads to wrong information

I have a Flask application where user can search for a room in a city by typing in the cityname.
When a cityname is typed in the user is redirected to a result page, where I use flask google maps to show available rooms on the map with markers.
I have two different marker images (for free users and for users who paid):
mymap.markers['static/img/Map-Marker-Marker-Outside-small.png'] = markerlist
mymap.markers['static/img/Map-Marker-Marker-Outside-Pink.png'] = markerlist_bezahlt
I populate the markers with a list, where all other informations are stored, f.e. the room and the rooms image, plus it is clickable and redirects on click to the details page.
Here is the whole method which creates the map and the markers depending on whether user has payed or is free (findroomcity is the cityname which a searching user has typed in):
location = geolocator.geocode(findroomcity)
if location.latitude is not None:
mymap = Map(
identifier="view-side",
lat=location.latitude,
lng=location.longitude,
infobox=[],
markers=[],
zoom = 12
)
else:
print "location is none"
all_users = User.query.order_by(desc('bezahlt')).all()
markerlist = []
markerlist_bezahlt = []
for room in all_rooms_in_city:
if room.stadt == findroomcity.lower():
try:
location2 = geolocator.geocode(room.stadt + " " + room.strasse + " " + room.hausnr, timeout=2)
for user in all_users:
if user.id == room.users_id:
if user.bezahlt == False:
markerlist.append((location2.latitude, location2.longitude))
mymap.infobox.append(r'''<a href='/details/''' + str(room.id) + "'>" + r'''<img class='marker-img' src='../static/userimg/''' + room.hauptbild + "'/>")
else:
markerlist_bezahlt.append((location2.latitude, location2.longitude))
mymap.infobox.append(r'''<a href='/details/''' + str(room.id) + "'>" + r'''<img class='marker-img' src='../static/userimg/''' + room.hauptbild + "'/>")
except GeocoderTimedOut as e:
print "in der schleife timeout", e
except AttributeError as e:
print "in der schleife attributeerror", e
mymap.markers['static/img/Map-Marker-Marker-Outside-small.png'] = markerlist
mymap.markers['static/img/Map-Marker-Marker-Outside-Pink.png'] = markerlist_bezahlt
The problem is that some markers have the wrong information stored. I guess it is because I am splitting into two markers?
Here is a life example from heroku:
Heroku for testing
Search for "Dortmund" and check the two small blue markers (these are both "FREEUSERZIMMER") but one of them shows a payed room
This is just a guess— but from looking at the source code of your search page showing the markers I can see duplicates of var marker_0 and others. I presume you're iterating through the markerlist from a zero index, then the markerlist_bezahlt basing their marker_x names off their index location, so the second list overrides the data for the first markers.

Categories

Resources