Hashing with hashlib with user interaction - python

I am trying to create a hashing function with user interaction.
The idea is that the user chooses which hash he/she wants (i.e. md5, sha1 and so forth) and the program does the rest.
My code:
hashstring = "hashlib" + finalHash
filePath = open(chosenFile, 'rb')
data = filePath.read(8192)
if not data:
return
hashstring.update(data) # The line that causes error
return hashstring.hexdigest()
finalHash is from a dictionary containing (lets say md5 is chosen) '.md5()' so the string from hashstring is 'hashlib.md5().
I get the error: AttributeError: 'str' object has no attribute 'update', the error points me to the obvious: hashstring is a string (as i declared it), my question goes: How do i convert or in other way make it useable as it is intended?

You could use getattr:
import hashlib
chosenFile = '/etc/passwd'
finalHash = input('Which hash function?') # raw_input in Python 2
assert finalHash in ['md5', 'sha1'] # Optional
h = getattr(hashlib, finalHash)
h.update(open(chosenFile, 'rb').read())
print(h.hexdigest())
Note that the input must not contain dots or parentheses. If you want to allow the user to input md5() or so, you'll have to strip the parentheses first.

Related

Account/Password Distribution Tool - stuck creating an object from csv

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.

Invalid salt error when comparing plain text and hash with bcrypt

I'm trying to compare a saved hash and a user input in python using bcrypt. My code:
while passnotcorrect == True:
password = input("Enter password: ")
password = password.encode('utf-8')
file = open('password.txt', 'r')
checkhash = file.read()
file.close()
checkhash = checkhash.encode('utf-8')
if bcrypt.checkpw(password, checkhash):
passnotcorrect = False
os.system('cls||clear')
else:
print("Password is incorrect \n")
The error:
ValueError: Invalid salt
I'd really like some help with this. I'm not sure why this function would require the salt in the first place. Thanks
A little late but I think your issue is that you're trying to compare 'password' which is utf8 encoded string input with 'checkhash', another string read from a file.
Bcrypt.checkpw() takes in a UTF8 encoded string for the password to check as the first argument followed by the UTF8 encoded hash to compare the password being provided against to see if the provided pass matches the hash pass.
TLDR; you're passing two strings to the checkpw method, when the second argument needs to be the hash you're comparing against (gold standard).
db_pass = "pw-string123" # from database
password = "pw-string123" # from input
db_hashed_pass = bcrypt.hashpw(db_pass.encode('utf8'), bcrypt.gensalt())
print(f'Hashed pass to save in db: {db_hashed_pass}')
is_pass_matching = bcrypt.checkpw(password.encode('utf8'), db_hashed_pass)
print(f'Do passwords match? {is_pass_matching}')
Make sure your hashed password isn't being truncated (length matches) upon entry or retrieval.

object supporting the buffer API required sha256 error

I want to hash some 4 digit numbers
but it gives me (object supporting the buffer API required) error
here's my code
import hashlib
import itertools as it
number=[0,1,2,3,4,5,6,7,8,9]
code = hashlib.sha256()
passwords = list(it.permutations(number, 4))
#hpass is hash password
for hpass in passwords :
code.update(passwords)
print(hpass)
and the output is
Traceback (most recent call last):
File "c:\Users\Parsa\Desktop\project\Untitled-2.py", line 11, in <module>
code.update(passwords)
TypeError: object supporting the buffer API required
the update function of hashlib.sha256 instance require the bytes-like object
Update the hash object with the bytes-like object.
https://docs.python.org/3/library/hashlib.html
and also it seems input passwords list at update
It is hard to know the intention of your code.
but I guess you wanna get a set of hashes by 4 digit numbers
if it is right try this.
import hashlib
import itertools as it
number=[0,1,2,3,4,5,6,7,8,9]
passwords = list(it.permutations(number, 4))
# hpass is hash password
for hpass in passwords :
encoded_hpass = ''.join(map(str, hpass)).encode('ascii')
code = hashlib.sha256()
code.update(encoded_hpass)
print(encoded_hpass)
print(code.digest())
Output
b'0123'
b'\x1b\xe2\xe4R\xb4mz\r\x96V\xbb\xb1\xf7h\xe8$\x8e\xba\x1bu\xba\xede\xf5\xd9\x9e\xaf\xa9H\x89\x9aj'
b'0124'
b'\x91\xb1\xe2#\xed\x10?)\x1c\x16v\\\xb2\x01\xa9\xe4\xf2\xc2?\xf4\x05pP\xb9\xfdxW\x1f7:\xce='
b'0125'
b'\x17\x9f\x91-Q]\xdb\x97\xa0\x8f\xee\xb4\xe3v\x99aH\xda;\xb7\xcb]\x97K\x81<\x8a\xfb\xdcaf+'
b'0126'
b'\x9d\xa4\x84d|\xdd\xd7\x98]\x9e\xf5\x06\xf9\xbd\x15\x80\xf5\xa8\xdc\x06R8\xdbp\x1b\xc5~\x08\xa3<\\\xa9'
b'0127'
b'h|\xdf<\xae\xaa\x88\x8b\x00\x0e\xdfJ\x01\xd1(\xe3\xb3 &\xb0O\xe2H\xaa0\xab/\xab\xa6\xd3#3'
b'0128'
b'\xee\xb9\xff>\xa6X,\xe2\xbf\x03\xb9\xbb\xff\x95\x88"\x90\xb8\xa8\xe5(\xa3\x91\xbc5i\x17\x92\x8fr\x1c\x06'
b'0129'
b'-\x90|u\xaa\xb2$\x85\x0bkv\xd1^/\xd4q$\x8e\xdfq]\xe8\xf7\x9d\xc8L-A\x1ff?\x88'
b'0132'
b"\xa7H\x02\x8b\x05\x18\xda\x98\xd8\xd2F\xe6\x1a8\x96\xa6w\x05\x97^'\xc3\xa0B\xb1E\r\xa9\\\xe3\x9bU"
b'0134'
....

How to save output in python to .txt file

So basically i bought a book that teaches the basics of python and how to create a random number generator so I decided to go one step further and make a random password generator I found a tutorial online that gave me a good example of why and what is used to make a password generator but i want the output to be saved to a .txt file I do not know what i need to implement to get the result i want this is what i have i'm using python3.
import random
chars = 'abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!, #,#$%^&*.'
number = input('Number of passwords - ')
number = int(number)
length = input('password length? - ')
length = int(length)
answer = input
for P in range(number):
password = ''
for C in range(length):
password += random.choice(chars)
print(password)
password = open("passlist.txt", "a")
password.write(password)
password.close()
file = open('passlist', 'w')
file.write(password)
file.close()
this is what i get in shell
Traceback (most recent call last):
File "C:\User\Desktop\passgen.py", line 21, in <module>
password.write(password)
TypeError: write() argument must be str, not _io.TextIOWrapper
When you open a new file and set it equal to a variable, you are actually creating an _io.TextIOWrapper object. So in this line of code, you are creating this object and storing it in password, getting rid of the password generated in the previous lines of code.
password = open("passlist.txt", "a")
You are then trying to write to the passlist.txt file with this line:
password.write(password)
You are telling password, now an _io.TextIOWrapper object, to write to the passfile.txt the _io.TextIOWrapper object, not the password generated beforehand. This function is expecting a string, and you are now passing an _io.TextIOWrapper object. Since password is no longer a string, that is why you are running into the error.
To fix this, I would suggest creating a new variable:
txtFileWriter = open("passlist.txt", "a")
txtFileWriter.write(password)
txtFileWriter.close()
You may find that after fixing this, only one value is being stored inside your text file. I would recommend properly nesting your for loops:
for P in range(number):
password = ''
for C in range(length):
password += random.choice(chars)
print(password)
The meaning of these for loops can be translated as:
For each password, set the password = ' ' and for each character, add one random character to password.
The problem with this is that you will only have one password after the for loops are complete. You are setting the password value to ' ' each time you run through the outer loop. The only password that will be saved, will be the last value. In order to fix this, I recommend using a list.
I recommend reading through this documentation
I don't want to spoon feed the answers since I realize you are learning python, so I will leave it here. You will want to create a list and then append a value to that list each time you generate a password. After some reading, hopefully this will make sense.
filename = 'passlist.txt'
with open (filename, 'a') as file_object:
file_object.write(password)
Using with will close the file once access is no longer needed.
You also need a list to append your passwords ;)
The error originates from password being re-assigned in password = open("passlist.txt", "a"). This causes and error in the next line as you are attempting to pass password as parameter to itself in password.write(password).
Some farther assistance
You have the right idea but you forgot to indent. All the lines below for P in range(number): should be indented because the program must generate and write a new password until it has satisfied the required amount of passwords.
The password = open("passlist.txt", "a")
password.write(password)
password.close() lines are unnecessary as you are overriding the generated password and assigning that password variable to something that is not a string; that is why you are getting that error.
Here is the code with the adjustments.
import random
chars = 'abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!, #,#$%^&*.'
number = input('Number of passwords - ')
number = int(number)
length = input('password length? - ')
length = int(length)
answer = input
for P in range(number):
password = ''
for C in range(length):
password += random.choice(chars)
print(password)
password += "\n" # writes the password in a new line
file = open('passlist.tx', "a")
file.write(password)
file.close()

Python Authentication API

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>

Categories

Resources