I am fairly new to python programming and after finishing a bunch of beginners trainings id like to get some hands on experience.
My idea was to develop a account/password distribution tool.
What it should do is:
Import csv with accounts, users, permissions (Username1,Account1-PasswordPart1, Account2-PasswordPart2)
iterate through accounts.csv (generate and attach pw to account object)
iterate through users.csv (generate encrypted zip with *.txt for each users that contains accounts and half the password based on the permissions.csv)
1. Import
The import was fairly easy to implement.
2. Generate Password
This is the function I use to generate the passwords:
def pw_generator(length):
#define data
lower = string.ascii_lowercase
upper = string.ascii_uppercase
num = string.digits
symbols = string.punctuation
#string.ascii_letters
#combine the data
all = lower + upper + num + symbols
#use random
randompw = random.sample(all,length)
#create the password
password = "".join(randompw)
#print the password
return password
3. Use accounts.csv and make an object out of it
This is were im currently stuck. I tried this .. (and many other approaches)
class account:
def __init__(self,accountname,password):
self.accountname = accountname
self.password = password
acc_list = []
with open('accounts.csv', newline='') as csv_file:
reader = csv.reader(csv_file)
next(reader, None) # Skip the header.
for accountname, password in reader:
acc_list.append(account(account, password))
account.password=pw_generator(16)
print(accountname, account.password)
This gives me a list of the accountnames and passwords but I dont see how i can use them afterwards as an array..
Any ideas?
Thanks!
First, you have dug yourself a hole by giving a class a lowercase name.
This thing:
acc_list.append(account(account, password))
If you rename the class account into class Account and refactor the code, you'll see that it doesn't make any sense:
acc_list.append(Account(Account, password))
You create an instance of a class Account by giving it the class Account as an accountname. It doesn't seem like the thing you want to do.
And then you also change an undeclared class attribute (not the instance attribute, but the class attribute!):
Account.password=pw_generator(16)
Which also looks extremely suspicious, to put it mildly.
Second, it's not obvious what the field password should be in the end. Is it the value you read from .csv? Or some autogenerated pw?
You probably wanted to do something like this:
for accountname, password in reader:
acc_instance = Account(accountname, password) # Create an instance
acc_list.append(acc_instance) # add the instance to the list
print(acc_instance.accountname, acc_instance.password) # print the instance
# Then you can do whatever you like with the list.
# For example you could redefine all passwords in all accounts and print new credentials:
for acc in acc_list:
acc.password = pw_generator(16)
print(acc.accountname, acc.password)
# Or save this list in whatever form you like.
Related
After extracting some of the email's data, I would like to move the email to a specified folder with python. I've searched and haven't seemed to find what I need.
Has anyone done this before?
Per a comment, I've added my current logic in hopes that it will clarify my problem. I loop through my folder, extract the details. After doing that, I want to move the email to a different folder.
import win32com.client
import getpass
import re
'''
Loops through Lotus Notes folder to view messages
'''
def docGenerator(folderName):
# Get credentials
mailServer = 'server'
mailPath = 'PubDir\inbox.nsf'
# Password
pw = getpass.getpass('Enter password: ')
# Connect
session = win32com.client.Dispatch('Lotus.NotesSession')
# Initializing the session and database
session.Initialize(pw)
db = session.GetDatabase(mailServer, mailPath)
# Get folder
folder = db.GetView(folderName)
if not folder:
raise Exception('Folder "%s" not found' % folderName)
# Get the first document
doc = folder.GetFirstDocument()
# If the document exists,
while doc:
# Yield it
yield doc
# Get the next document
doc = folder.GetNextDocument(doc)
# Loop through emails
for doc in docGenerator('Folder\Here'):
# setting variables
subject = doc.GetItemValue('Subject')[0].strip()
invoice = re.findall(r'\d+',subject)[0]
body = doc.GetItemValue('Body')[0].strip()
# Move email after extracting above data
# ???
As you will move the document before getting the next one, I'd recommend to replace your loop with
doc = folder.GetFirstDocument()
while doc:
docN = folder.GetNextDocument(doc)
yield doc
doc = docN
And then to move the message to the proper folder you need
doc.PutInFolder(r"Destination\Folder")
doc.RemoveFromFolder(r"Origin\Folder")
Of course, take care of escaping your backslashes or using raw strings literals to pass correctly the view name.
doc.PutInFolder creates the folder if it doesn't exist. In that case the user needs to have permissions to create public folders, otherwise the created folder will be private. (If the folder already exists, of course, this is not a problem.)
This question already has answers here:
I need to securely store a username and password in Python, what are my options? [closed]
(8 answers)
Closed 5 years ago.
I am trying to create a program that asks the user for, in this example, lets say a username and password, then store this (I assume in a text file). The area I am struggling with is how to allow the user to update this their password stored in the text file? I am writing this in Python.
import getpass
import os
import bcrypt
new=None
def two_hash():
master_key = getpass.getpass('enter pass word ')
salt = bcrypt.gensalt()
combo = salt + master_key
hashed = bcrypt.hashpw(combo , salt)
allow = raw_input('do you want to update pass ')
if allow == 'y':
new = getpass.getpass('enter old pass word ')
combo = salt + new
bcrypt.hashpw(combo , salt)
if ( bcrypt.hashpw(combo , salt) == hashed ):
new = getpass.getpass('enter new pass ')
print new
else :
pass
if __name__ == '__main__':
two_hash()
Note 1 : i wanted to split my code to some function but i can't so help for split it to some function
Because you've asked to focus on how to handle the updates in a text file, I've focused on that part of your question. So, in effect I've focused on answering how would you go about having something that changes in a text file when those changes impact the length and structure of the text file. That question is independent of the thing in the text file being a password.
There are significant concerns related to whether you should store a password, or whether you should store some quantity that can be used to verify a password. All that depends on what you're trying to do, what your security model is, and on what else your program needs to interact with. You've ruled all that out of scope for your question by asking us to focus on the text file update part of the problem.
You might adopt the following pattern to accomplish this task:
At the beginning see if the text file is present. Read it and if so assume you are doing an update rather than a new user
Ask for the username and password. If it is an update prompt with the old values and allow them to be changed
Write out the text file.
Most strategies for updating things stored in text files involve rewriting the text file entirely on every update.
Is this a single user application that you have? If you can provide more information one where you're struggling
You can read the password file (which has usernames and passwords)
- When user authenticate, match the username and password to the combination in text file
- When user wants to change password, then user provides old and new password. The username and old password combination is compared to the one in text file and if matches, stores the new
Try using JSON.
An example of a json file would be this:
{
"Usernames": {
"Username": [
{
"Password": "Password123"
}
]
}
}
Then to edit the json:
jsonloads = json.loads(open('json.json').read()) #Load the json
username = input("Enter your username: ") #Get username as a string
for i in jsonloads["Usernames"]: #Iterate through usernames
if i == username: #If the username is what they entered
passw = input("New password: ") #Ask for new password
jsonloads["Usernames"][i][0]["Password"] = passw #Set the password
jsonFile = open("json.json", "w+") #Open the json
jsonFile.write(json.dumps(jsonloads, indent=4)) #Write
jsonFile.close() #Close it
break #Break out of the for loop
else: #If it remains unbroken
print("You aren't in the database. ")
user = input("Username: ") #Ask for username
passw = input("Password: ") #Ask for password for username
item = {"Password":pass} #Make a dict
jsonloads["Usernames"].update({user: item}) #Add that dict to "Usernames"
with open('json.json','w') as f: #Open the json
f.write(json.dumps(jsonloads, indent=4)) #Write
Something like that should work, haven't tested it though.
Also, remember to always encrypt passwords!
I am attempting to create a login script. I have the usernames and passwords in a text file that I want python to read and check through to find usernames and passwords.
The biggest problem I am having is "attaching" the password to a username. I can currently only scan the whole of the document for both but not necessarily attached to each other.
#-------------------------------------------------------------------------------
# Name: LogIn
# Purpose: Logging In
#
# Author: Dark Ariel7
#
# Created: 19/02/2013
# Copyright: (c) Dark Ariel7 2013
# Licence: I take no responsability for anything.
#-------------------------------------------------------------------------------
from getpass import getpass
from time import sleep
Database = open("C:\\Users\Dark Ariel7\\Desktop\\USB BAckup\\Scripts\\Database.txt", encoding='utf-8')
Username = ("")
Password = ()
def LogIn():
Database = open("C:\\Users\Dark Ariel7\\Desktop\\USB BAckup\\Scripts\\Database.txt", encoding='utf-8')
Data = (Database.read())
Username = ("")
Password = ()
Username = input("Username: ")
Password = getpass(str("Password: "))
LogIn= ",".join((Username,Password))
if LogIn in Data:
print("Welcome, " + Username)
sleep(3)
pass
else:
print("Failed, Sucker!")
sleep(5)
exit()
LogIn()
If you guys could help me figure out what exactly .join part is for that would be great. Should i make a dictionary and use the index for a login sheet? I also want some general feedback on how to make the code better.
This is the txt file that it will be reading:
[Dark Ariel7,123456]
[Poop,Anko]
*Edit Sorry guys I forgot to mention that I am using python 3 not 2. Thanks so far. Very quick replies. Also after the last else instead of exit what do I put so that the function loops until I get the right username password combo?
The ".join" part joins the username and password that the user types in with a comma between them (i.e. Poop,Anko) because that's the format in which it's stored in the database, so you can search for it that way.
Here's your code, edited up a bit, with some comments about functionality and style.
from getpass import getpass
from time import sleep
Database = open("C:\\Users\Dark Ariel7\\Desktop\\USB BAckup\\Scripts\\Database.txt", encoding='utf-8')
# These next two lines aren't necessary - these variables are never used; you may want to read up about namespaces: http://bytebaker.com/2008/07/30/python-namespaces/
#Username = ("")
#Password = ()
def LogIn():
Database = open("C:\\Users\Dark Ariel7\\Desktop\\USB BAckup\\Scripts\\Database.txt", encoding='utf-8')
# Removed the parentheses; they have no effect here. Putting parens around lone statements doesn't have any effect in python.
Data = Database.read()
# These next two lines are pointless, because you subsequently overwrite the values you give these variables. It looks like you're trying to "declare" variables, as you would in Java, but this isn't necessary in python.
# Username = ("")
# Password = ()
# Changed this from "input" to "raw_input" because input does something else that you don't want.
Username = raw_input("Username: ")
Password = getpass(str("Password: "))
LogIn= ",".join((Username,Password))
if LogIn in Data:
print("Welcome, " + Username)
# Not sure why you want the script to sleep, but I assume you have your reasons?
sleep(3)
# no need to pass
# pass
else:
print("Failed, Sucker!")
sleep(5)
# exit() isn't necessary - the function will end by itself.
# exit()
LogIn()
The basic problem you have is that your file has [ ] surrounding the username and password combination, but you fail to account for this.
There are some other stylistic issues with your code, here is an edited version:
import getpass
from time import sleep
password_file = r'C:\....\Database.txt'
def login(user,passwd):
''' Checks the credentials of a user '''
with open(password_file) as f:
for line in f:
if line.strip(): # skips blank lines
username,password = line.split(',') # this gets the individual parts
username = username[1:] # gets rid of the [
password = password[:-1] # the same for the password
if user == username and password == passwd:
return True
return False
if __name__ == '__main__':
username = input('Please enter the username: ')
passwd = getpass('Please enter the password: ')
if login(user,passwd):
print('Welcome {1}'.format(user))
sleep(3)
else:
print('Failed! Mwahahaha!!')
sleep(5)
To start off with, you don't need () to "initialize" variables; more to the point in Python you don't need to initialize variables at all. This is because Python doesn't have variables; but rather names that point to things.
Next, the python style guide says that variable names should be lowercase, along with method names.
Now - the main part of the code:
>>> username, password = '[username,sekret]'.split(',')
>>> username
'[username'
>>> password
'sekret]'
I used split() to break up the line into the username and password parts; but as you see there is still the [ messing things up. Next I did this:
>>> username[1:]
'username'
>>> password[:-1]
'sekret'
This uses the slice notation to strip of the leading and ending characters, getting rid of the [ ].
These lines:
with open(password_file) as f: # 1
for line in f: # 2
if line.strip(): # skips blank lines
Do the following:
Opens the file and assigns it to the variable f (see more on the with statement)
This for loop steps through each line in f and assigns the name line to each line from the file.
The third part makes sure we skip blank lines. strip() will remove all non-printable characters; so if there are no characters left, the line is blank and will have a 0 length. Since if loops only work when the condition is true, and 0 is a false value - in effect what happens is we only operate on non-blank lines.
The final part of the code is another if statement. This is a check to make sure that the file will run when you execute it from the command prompt.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions must demonstrate a minimal understanding of the problem being solved. Tell us what you've tried to do, why it didn't work, and how it should work. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I would like to prompt the user to input number of users to run and email addresses to populate a csv file. I am getting some syntax error. How do I get this working ?
enter code here
import csv
# Define users
valid_input = False
while not valid_input:
users =raw_input('Number of users: ')
try:
users = range(0,int(users)
valid_input = True
except:
print "Invalid input"
pass
First_Name = ["Test"+str(user) for user in range(1, users+1)]
Last_Name = ["User%s" %user for user in users]
email_addresses = []
for user in users:
email= raw_input("Email domain for user %d: " %user)
email_addresses.append(last_names[user] + email)
Password = ["Password1" for user in users]
Group =["Test" for user in users]
Admin = ["Yes" for user in users]
# open a file for writing.
# open a file for writing.
with open('users.csv', 'wb') as csv_out:
writer = csv.writer(csv_out)
writer.writerows(zip(Email_Address, Password, First_Name, Last_Name, Group, Admin))
The line
Email_Address = (raw_input('Email_Address') [Last_Names + "Email_Address " for Last_Names inLast_Name]])
is invalid syntax. It's actually very difficult to tell what you're trying to do with that line, but it is very invalid syntax.
Also you seem to be misunderstanding iteration in python. On your first line you prompt for a single number and then try to iterate through it in multiple other places, which I'm guessing is pretty far from your intention.
users = (raw_input('number of users'))
will set users equal to a single string. I'm guessing that what you'd actually want is something more like this:
valid_input = False
while not valid_input:
users =raw_input('Number of users: ')
try:
users = range(0,int(users))
valid_input = True
except:
print "Invalid input"
pass
I've been reading through the code some more and while it seems to be pretty far from what you've written there, I'm guessing that you want to prompt the user for an email address for each user. If that is indeed the case, this is how you would do it:
email_addresses = []
for user in users:
email = raw_input("Email address for user %d: " %user)
email_addresses.extend([email + last_name for last_name in last_names])
Apparently I was mistaken about your intent, here's a solution for what you're looking for:
email_addresses = []
for user in users:
email= raw_input("Email domain for user %d: " %user)
email_addresses.append(last_names[user] + email)
Also, a couple style notes:
Try to keep all of your variable names as descriptive as possible. For instance, the last_name list you've got doesn't actually have last names, but holds user ids, so user_ids would be a better name
If you are going to adopt a pluralization nomenclature then make sure to pluralize lists and then make sure that the items can be referenced as the singular version instead of the other way around. For example:
last_name = [#some list]
[#something for last_names in last_name]
is just confusing. It should be:
last_names = [#some_list]
[#something for last_name in last_names]
Choose either snake case (like_this) or title case (likeThis) and stick with it. Nothing is more annoying than having to scroll through a lost codebase and figure out which case a particular variable is using.
I'm not into Python at all, but it seems to be 1 square bracket too much at the end of this line :
Email_Address = (raw_input('Email_Address') [Last_Names + "Email_Address " for Last_Names inLast_Name]])
After this line:
users = (raw_input('number of users'))
users is a string. Let's say you enter 100.
Now, you iterate over users:
First_Name = ["Test"+str(user) for user in users]
Strings are iterable, so user takes on the individual characters of the string '100'. That is, user will first be '1', then '0', then '0' again; you get Test1 then Test0 then Test0 rather than the 100 items I expect you expect.
You probably want to convert the input to an integer:
users = int(raw_input('number of users'))
And then iterate over a range (I'm assuming you want 1 through n rather than 0 through n-1:
First_Names = ["Test"+str(user) for user in range(1, users+1)]
I've also taken the liberty of changing the name of your variable to First_Names as what you have is a list of the first names, not a single first name.
Unfortunately, I don't really have the time to go into the rest of the problems with your code, of which there are many (including the question about input that you're actually asking), but that ought to get you started fixing it up.
I'm looking for a python library that will help me to create an authentication method for a desktop app I'm writing.
I have found several method in web framework such as django or turbogears.
I just want a kind of username-password association stored into a local file.
I can write it by myself, but I'm really it already exists and will be a better solution (I'm not very fluent with encryption).
dbr said:
def hash_password(password):
"""Returns the hashed version of a string
"""
return hasher.new( str(password) ).hexdigest()
This is a really insecure way to hash passwords. You don't want to do this. If you want to know why read the Bycrypt Paper by the guys who did the password hashing system for OpenBSD. Additionally if want a good discussion on how passwords are broken check out this interview with the author of Jack the Ripper (the popular unix password cracker).
Now B-Crypt is great but I have to admit I don't use this system because I didn't have the EKS-Blowfish algorithm available and did not want to implement it my self. I use a slightly updated version of the FreeBSD system which I will post below. The gist is this. Don't just hash the password. Salt the password then hash the password and repeat 10,000 or so times.
If that didn't make sense here is the code:
#note I am using the Python Cryptography Toolkit
from Crypto.Hash import SHA256
HASH_REPS = 50000
def __saltedhash(string, salt):
sha256 = SHA256.new()
sha256.update(string)
sha256.update(salt)
for x in xrange(HASH_REPS):
sha256.update(sha256.digest())
if x % 10: sha256.update(salt)
return sha256
def saltedhash_bin(string, salt):
"""returns the hash in binary format"""
return __saltedhash(string, salt).digest()
def saltedhash_hex(string, salt):
"""returns the hash in hex format"""
return __saltedhash(string, salt).hexdigest()
For deploying a system like this the key thing to consider is the HASH_REPS constant. This is the scalable cost factor in this system. You will need to do testing to determine what is the exceptable amount of time you want to wait for each hash to be computed versus the risk of an offline dictionary based attack on your password file.
Security is hard, and the method I present is not the best way to do this, but it is significantly better than a simple hash. Additionally it is dead simple to implement. So even you don't choose a more complex solution this isn't the worst out there.
hope this helps,
Tim
I think you should make your own authentication method as you can make it fit your application best but use a library for encryption, such as pycrypto or some other more lightweight library.
btw, if you need windows binaries for pycrypto you can get them here
Treat the following as pseudo-code..
try:
from hashlib import sha as hasher
except ImportError:
# You could probably exclude the try/except bit,
# but older Python distros dont have hashlib.
try:
import sha as hasher
except ImportError:
import md5 as hasher
def hash_password(password):
"""Returns the hashed version of a string
"""
return hasher.new( str(password) ).hexdigest()
def load_auth_file(path):
"""Loads a comma-seperated file.
Important: make sure the username
doesn't contain any commas!
"""
# Open the file, or return an empty auth list.
try:
f = open(path)
except IOError:
print "Warning: auth file not found"
return {}
ret = {}
for line in f.readlines():
split_line = line.split(",")
if len(split_line) > 2:
print "Warning: Malformed line:"
print split_line
continue # skip it..
else:
username, password = split_line
ret[username] = password
#end if
#end for
return ret
def main():
auth_file = "/home/blah/.myauth.txt"
u = raw_input("Username:")
p = raw_input("Password:") # getpass is probably better..
if auth_file.has_key(u.strip()):
if auth_file[u] == hash_password(p):
# The hash matches the stored one
print "Welcome, sir!"
Instead of using a comma-separated file, I would recommend using SQLite3 (which could be used for other settings and such.
Also, remember that this isn't very secure - if the application is local, evil users could probably just replace the ~/.myauth.txt file.. Local application auth is difficult to do well. You'll have to encrypt any data it reads using the users password, and generally be very careful.
If you want simple, then use a dictionary where the keys are the usernames and the values are the passwords (encrypted with something like SHA256). Pickle it to/from disk (as this is a desktop application, I'm assuming the overhead of keeping it in memory will be negligible).
For example:
import pickle
import hashlib
# Load from disk
pwd_file = "mypasswords"
if os.path.exists(pwd_file):
pwds = pickle.load(open(pwd_file, "rb"))
else:
pwds = {}
# Save to disk
pickle.dump(pwds, open(pwd_file, "wb"))
# Add password
pwds[username] = hashlib.sha256(password).hexdigest()
# Check password
if pwds[username] = hashlib.sha256(password).hexdigest():
print "Good"
else:
print "No match"
Note that this stores the passwords as a hash - so they are essentially unrecoverable. If you lose your password, you'd get allocated a new one, not get the old one back.
import hashlib
import random
def gen_salt():
salt_seed = str(random.getrandbits(128))
salt = hashlib.sha256(salt_seed).hexdigest()
return salt
def hash_password(password, salt):
h = hashlib.sha256()
h.update(salt)
h.update(password)
return h.hexdigest()
#in datastore
password_stored_hash = "41e2282a9c18a6c051a0636d369ad2d4727f8c70f7ddeebd11e6f49d9e6ba13c"
salt_stored = "fcc64c0c2bc30156f79c9bdcabfadcd71030775823cb993f11a4e6b01f9632c3"
password_supplied = 'password'
password_supplied_hash = hash_password(password_supplied, salt_stored)
authenticated = (password_supplied_hash == password_stored_hash)
print authenticated #True
see also gae-authenticate-to-a-3rd-party-site
Use " md5 " it's much better than base64
>>> import md5
>>> hh = md5.new()
>>> hh.update('anoop')
>>> hh.digest
<built-in method digest of _hashlib.HASH object at 0x01FE1E40>