I am starting my adventure with Python and object oriented programming.
I wrote a script for salting and hashing password. My main goal is practice with OOP, not cryptography. I know there is no error handling.
Wonder how improve my code it and make more object oriented. It would be nice if someone more experienced can take a look and give me some advice how to make it better. Any help for newbie would be great!
Description:
The script is not really useful in real life.
1st part:
Hash and salt password and next encode to base64 with added salt (needed for future comparing hashes). Algorithm: base64( SHA256(password + salt) + salt)
Salt is X random bytes where X can be specify but by default it is 16.
2nd part (some kind of authorization):
Compare input hash (e.x. from database) with new created hash from input plain password.
New salt is created from salt taken from input hash.
Code:
import base64
import hashlib
import os
class Hashing(object):
# base64( SHA256(password + salt) + salt)
# generate new salt (default 16 bytes)
def generate_new_salt(self, salt_ln=16):
self.new_salt = os.urandom(salt_ln)
print(f'new salt: {self.new_salt}')
return self.new_salt
# get salt from hash
def get_old_salt(self, input_hash, salt_ln=16):
self.old_salt = base64.b64decode(input_hash)[-salt_ln:]
print(f'old salt: {self.old_salt}')
return self.old_salt
# compute hash using parameters
def compute_hash(self, password, salt):
self.salt = salt
self.enc_password = password.encode()
# hashing SHA256(password + salt)
hash_object = hashlib.sha256(self.enc_password + salt)
# add salt to hash and encode to base64
hash_b64 = base64.b64encode(hash_object.digest() + salt)
print(f'new_hash: {hash_b64}')
return hash_b64
# create hash from new or old salt
def create_hash(self, password, salt_ln=16,old_salt=None):
if old_salt: #if old salt then use it
self.salt = old_salt
else: #else generate new salt
self.salt = Hashing().generate_new_salt(salt_ln)
hash = Hashing().compute_hash(password, self.salt)
return hash
# compare input hash with created using salt get from input
def compare_hashes(self, password, old_hash, salt_ln=16):
self.enc_password = password.encode()
#get salt from input hash
self.old_salt = Hashing().get_old_salt(old_hash, salt_ln)
#recreat input hash
re_hash = Hashing().create_hash(password,salt_ln, self.old_salt)
print(f'Compare: old_hash: {old_hash}')
print(f'Compare: new_hash: {re_hash}')
#compare
if re_hash.decode() == old_hash.decode():
return True
else:
return False
#code below is just for testing
NewSalt = Hashing().generate_new_salt()
Hash = Hashing().create_hash('pass')
OldSalt = Hashing().get_old_salt(Hash)
CompareHash = Hashing().compare_hashes('pass', Hash)
if CompareHash:
print('HASHES THE SAME')
else:
print('NOT THE SAME')
print(CompareHash)
Questions:
What is a real difference between these two? With and w/o self.X works
def generate_new_salt(self, salt_ln=16): self.new_salt = os.urandom(salt_ln) print(f'new salt: {self.new_salt}') return self.new_salt
def generate_new_salt(self, salt_ln=16): new_salt = os.urandom(salt_ln) print(f'new salt: {new_salt}') return new_salt
I have problem with passing default value of salt length,
salt_ln = 16
. For me it does not look nice when it is replicated in every method. Is there any way to do it more global?