简体   繁体   中英

Compare salted hashed passwords in Python for authorisation

In company we move some parts of the system from .NET to python. One of these parts is logging/authorization module. I need to implement in python CryptographyManager.CompareHash Method . It takes salted and hashed password from database and compares it with user input (plaintext). To do it I have to salt and hash user input and then check it with hashed password from database.

The password in the database was hashed by Microsoft Enterprise Library.Security.Cryptography . Here more details:

Symmetric Crypto Providers: algorithmType="System.Security.Cryptography.AesManaged name="AES"

Hash Providers : algorithmType="System.Security.Cryptography.SHA256Managed saltEnabled="true" name="SHA256"

I found that password is slated in that way: Base64(salt + SHA256(salt + password)) . The salt is the first 16 bytes from the hashed password

What I am trying to do is get salt from hashed password in database and next hash and salt user input (plain text) to compare both.

Unfortunately, in the end there is no succes. Hashes are diffrent. Probably I am doning something wrong with de/encoding

My code looks like that:

import base64
import hashlib

hash = 'EwxBhfN0fM5Puv8/z+3/L50QvdU6BHFb4XQU9xtye/mOXJ8tBPc3tIyW7dEiZrvA'
password = 'some_plain_password' 

#password = password.encode()
password = base64.b64decode(password)

#hash to byte
b_hash = base64.b64decode (hash)
print(b_hash)

#get salt, first 16 bytes
salt = b_hash[:15]
salt=base64.b64encode(salt)
print(salt)

m = hashlib.sha256()
m.update(salt)
m.update(password)

print(m.hexdigest())

It's a bit tricky to do this without an example plaintext and hash to verify the results, but your code should implement the algorithm you list in your question:

Base64(salt + SHA256(salt + password))

I think you want something like this:

import base64
import hashlib

hash = 'EwxBhfN0fM5Puv8/z+3/L50QvdU6BHFb4XQU9xtye/mOXJ8tBPc3tIyW7dEiZrvA'
salt = base64.b64decode(hash)[:16]  # Use 16 here, not 15

password = 'some_plain_password'

# First let's do the SHA256(salt + password) part
m = hashlib.sha256()
m.update(salt)
m.update(password.encode('utf-8'))

# Now let's feed that into the Base64 part
new_hash = base64.encode(salt + m.digest())

My post is not 100% answer but more the end of the story. The problem is that there is no official source how works CryptographyManager.Compare/Create Hash I tried a lot of combinations with Base64(salt + SHA256(salt + password)) but without succes. Finally, I decide to rewrite C# code. If someone is looking for python code that is salting and hashing password and compare two hashes, below is my working example:

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_new_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_new_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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM