What does "append and prepend" twice mean EXACTLY?

Tell us what’s happening:
The project description states the following, but it is making me confused.

The function should take an optional second argument named use_salts . If set to true, each salt string from the file known-salts.txt should be appended AND prepended to each password from top-10000-passwords.txt before hashing and before comparing it to the hash passed into the function.

If you append and prepend the first salt to the first password BEFORE HASHING you get:

HAsnoiqHEh123456HAsnoiqHEh

You then hash it and get:

1d7be5cd7ad6b3d1d49f0275733c3f54e0891015

But if you then do the appending and prepending of the salt again BEFORE COMPARING IT TO THE HASH PASSED INTO THE FUNCTION you get:

HAsnoiqHEh1d7be5cd7ad6b3d1d49f0275733c3f54e0891015HAsnoiqHEh

Which is obviously going to give no match as it is way longer than the hash input into the function, such as:

dcc466796201f7232b22a03781110a8871fd038c

So I must be misunderstanding the wording. What do they want us to do exactly?

Your code so far

import hashlib
   
def crack_sha1_hash(hash, **kwargs):
    # Arguments for this function may be 1 or 2, so need to assign them to a variable first
    if kwargs == {}:
        use_salts = False
    elif kwargs == {'use_salts': True}:
        use_salts = True
    
    if use_salts == True:
        # 1) hash all 10000 passwords in the 'top-10000-passwords.txt' file using the SHA 1 algorithm and salts from the 'known-salts.txt' file
        top_10000_pws_file_content = open("top-10000-passwords.txt","r").read()
        top_10000_pws_list = top_10000_pws_file_content.split("\n")

        known_salts_file_content = open("known-salts.txt","r").read()
        salts_list = known_salts_file_content.split("\n")

        pws_plus_salts = [] #Append and prepend salts to each password
        for i in range(0,len(salts_list), 1):
            for j in range(0, len(top_10000_pws_list), 1):
                pws_plus_salts.append( salts_list[i] + top_10000_pws_list[j] + salts_list[i] )
        print(pws_plus_salts[:5])

        pwsplussalts_in_bytes = []
        for value in pws_plus_salts:
            pwsplussalts_in_bytes.append( value.encode('utf-8') )

        hashed_pws = []
        for value in pwsplussalts_in_bytes:
            hashed_pws.append( hashlib.sha1(value).hexdigest() )
        print(hashed_pws[:5])

        pwsplussalts_and_hashedpws = []
        for i in range(0, len(pws_plus_salts), 1):
            pwsplussalts_and_hashedpws.append( [pws_plus_salts[i], hashed_pws[i]] )
        print(pwsplussalts_and_hashedpws[:5])


        # 2) Compare each hashed top 10000 password with salts appended and prepended to the input hash - whichever hash matches is the password 
        for i in range(0, len(pwsplussalts_and_hashedpws), 1):
            if hash == pwsplussalts_and_hashedpws[i][1]:
                print('This is the password: ')
                return pwsplussalts_and_hashedpws[i][0]
        
        
        # 3) If no match, password was not in database
        return 'PASSWORD NOT IN DATABASE'
    
    else:
        # 1) hash all 10000 passwords in the 'top-10000-passwords.txt' file using the SHA 1 algorithm
        top_10000_pws_file_content = open("top-10000-passwords.txt","r").read()
        top_10000_pws_list = top_10000_pws_file_content.split("\n")

        pws_in_bytes = []
        for value in top_10000_pws_list:
            pws_in_bytes.append( value.encode('utf-8') )

        hashed_pws = []
        for value in pws_in_bytes:
            hashed_pws.append( hashlib.sha1(value).hexdigest() )

        pws_and_hashedpws = []
        for i in range(0, len(top_10000_pws_list), 1):
            pws_and_hashedpws.append( [top_10000_pws_list[i], hashed_pws[i]] )


        # 2) Compare each hashed top 10000 password to the input hash - whichever hash matches is the password 
        for i in range(0, len(pws_and_hashedpws), 1):
            if hash == pws_and_hashedpws[i][1]:
                print('This is the password: ')
                return pws_and_hashedpws[i][0]
        
        
        # 3) If no match, password was not in database
        return 'PASSWORD NOT IN DATABASE'


# The function should take an optional second argument named use_salts. If 
# set to true, each salt string from the file known-salts.txt should be appended 
# AND prepended to each password from top-10000-passwords.txt before hashing 
# and before comparing it to the hash passed into the function.
    

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36

Challenge: SHA-1 Password Cracker

Link to the challenge:

Salt is supposed to be added before hashing. Two variants are expected to be checked - with prepended salt and with appended salt. Minus the braces:

{salt}{password}
{password}{salt}
2 Likes

Although text reads as if both have to be done (“append AND prepend”):

{salt}{password}{salt}
1 Like

Yeah, wording can make it confusing. AND is there because both should be checked, changing it to OR makes it look like just one of the two is needed. If you’d have some idea how to make it clear, feel free to make PR on the boilerplate repository.

1 Like