How to hash an already hashed value for a given range? - python

I'm trying to design a One-Time-Password algorithm. I want to get a string input from the user and hash it repeatedly for a 100 times, then store each into an array. I'm stuck on the part that requires repeatedly hashing the string.
I've tried the basics, I know how to get the hash of a string value once using hashlib. In the code below, I tried applying it this way to do it for 10 times, but I feel like there's an easier way that actually works.
import hashlib
hashStore= []
password= input("Password to hash converter: ")
hashedPassword= hashlib.md5(password.encode())
print("Your hash is: ", hashedPassword.hexdigest())
while i in range(1,10):
reHash= hashlib.md5(hashedPassword)
hashStore.append(rehash)
i= i+1
print("Rehashed ",reHash.hexdigest())
However this code doesn't work. I'm expecting it to "re-hash" the value and each time it does so add it to the array.
Any and all help is appreciated :)

For-loops in Python can be implemented easier. Just write for i in range(10): without anything in the loop inside.
hashStore.append(rehash) uses rehash instead of reHash
You don't memoize your reHash so you are always try to hash the starting string
You should convert your hash to string if you want to rehash it: reHash.hexdigest().encode('utf-8')
Here is the full working code:
import hashlib
hashStore = []
password = input("Password to hash converter: ")
hashedPassword = hashlib.md5(password.encode())
print("Your hash is: ", hashedPassword.hexdigest())
reHash = hashedPassword
for i in range(10):
reHash = hashlib.md5(reHash.hexdigest().encode('utf-8'))
hashStore.append(reHash)
print("Rehashed ",reHash.hexdigest())

Use a for loop instead, initialize the hashStore with the initial hash, and rehash the last hashed hash (hashStore[-1]) in each loop:
import hashlib
password= input("Password to hash converter: ")
hashedPassword= hashlib.md5(password.encode())
print("Your hash is: ", hashedPassword.hexdigest())
hashStore= [hashedPassword]
for _ in range(1,100):
reHash = hashlib.md5(hashStore[-1].hexdigest().encode('utf-8'))
hashStore.append(reHash)
print("Rehashed ",reHash.hexdigest())

Related

Cracking a salted hash using a dictionary in python

im currently attempting a question where i have to crack a salted hash in python given the hash e77decd0e7c8a7b4688b010241bece45 and the salt "$goodluck$". I have tried downloading 10 million of the most popular passwords (https://github.com/danielmiessler/SecLists/blob/master/Passwords/Common-Credentials/10-million-password-list-top-1000000.txt), and using that as a dictionary. I then attach the salt to the word, encrypt it and then hash it. This is then compared to the given hash value. However i still have not been able to crack it. Here is my code:
import hashlib
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Hash import MD5
def dictionary_attack(password_hash):
dic = lines #extracted from file
pass_found = False
for word in dic:
word = word+"$goodluck$"
key = get_random_bytes(16)
cipher = AES.new(key, AES.MODE_EAX)
ciphertext, tag = cipher.encrypt_and_digest(word.encode('utf-8'))
hashed_val = MD5.new()
hashed_val.update(ciphertext)
hashed_val = hashed_val.hexdigest()
if hashed_val == password_hash:
pass_found = True
recovered_password = word
if pass_found:
print("Your password is: {}".format(recovered_password))
else:
print("Password not found")
dictionary_attack("e77decd0e7c8a7b4688b010241bece45")
Any help would be greatly appreciated. Thanks
Did you use this or this list?
Please try a reverse approach so see if you algorithm works or if there is something wrong:
pick a password
salt it
get the hash
generate some small list with that password and some others
feed that list and the hash to your function and see if it works
Ok, so that means that your code actually works and the password is not on the list. Instead of using that list, find the "The Top 500 Worst Passwords " and try them.
I don't know which library is faster, so just try it and get the duration for a reasonable amount of passwords to average out overhead, e.g. pick that many passwords that the duration is about one minute.

MD5 hash in Python

I have been given a file with user and passwords in the format: $id$salt$hashed.
Where ID stands for the type of encryption and id=1 stands for FreeBSD-style MD5.
There is an example in which I know the password= "alice"
jsmith: $1$kDHTx$WKRXXT1P7UtjvU7CQ9eWs/:10063:0:99999:7:::
So I have done this in Python to check
import hashlib
passw='alice'
salt='kDHTx'
hashed= hashlib.md5(salt+passw).hexdigest()
print('What i get is: '+hashed)
print('What i should: '+'WKRXXT1P7UtjvU7CQ9eWs')
But I dont even get the format correctly:
What i get is: ba359e6dd36371c4dc5c187aac11e0d8
What i should: WKRXXT1P7UtjvU7CQ9eWs
What am I doing wrong? Or even understanding wrong from the begining?
You need to use the crypt library instead of hashlib.
>>> import crypt
>>> crypt.crypt('alice', crypt.METHOD_MD5)
$1$tlyP8ine$I9F3AiUCIgOjREqbx6WUg0
The salt is generated by the function when you pass in crypt.METHOD_MD5.
To re-create an existing hash, you can pass it in as the second argument:
>>> crypt.crypt('alice', '$1$kDHTx$WKRXXT1P7UtjvU7CQ9eWs/')
$1$kDHTx$WKRXXT1P7UtjvU7CQ9eWs/

Computing a test hash with python pbkdf2_hmac-sha256 + salt not the same vaules

For a encryption class i'm in we were tasked to make a program to check a password if the computer knows the following defined information. The teacher gave us a working set of fixed information.
I am trying to write a python code to verfiery a given set of user data based upon the known and fixed...
digest method: HMAC-SHA256
rounds: 100000
salt:"e65814e4382759f85550029e723dc7e7"
password:"governor washout beak"
to output the derived: "5f37a3bd08ac1c7d163294a3cb192ed1407b62bbc6a6259fee55f6e53f754273"
This is my code to generate the derived to check the against the above derived...
key = hashlib.pbkdf2_hmac('sha256', b'governor washout beak', b'e65814e4382759f85550029e723dc7e7', 100000, dklen=32)
print(binascii.hexlify(key))
however I get "0ce7d2e654c0ba80e67348c9610ca1851312458166ee8c9e6d46666832a21b11"
instead. I don't understand what is missing.
the error is the code takes the salt from ascii >> binary not hex >> binary so
You want to use the binascii module:
import binascii
hexstr = 'e65814e4382759f85550029e723dc7e7'
binascii.unhexlify(hexstr)
b"\xe6X\x14\xe48'Y\xf8UP\x02\x9er=\xc7\xe7"
In python 3, this can be written as follows:
hexstr = 'e65814e4382759f85550029e723dc7e7'
pbkdf2_hmac_key = hashlib.pbkdf2_hmac('sha256', b'governor washout beak', bytes.fromhex(hexstr), 100000, dklen=32)
print(pbkdf2_hmac_key.hex())
# 5f37a3bd08ac1c7d163294a3cb192ed1407b62bbc6a6259fee55f6e53f754273

Zip Password functionality works wrong

I have a paradoxon, that I just cannot explain.
In short: I built a python script that is supposed to crack a zipped file, which is password protected.
This is what I've done:
(1) zip the text file:
zip --password bla zip3.zip myZip So the passphrase is "bla".
(2) Then I use the following Python Script:
import zipfile
import itertools
from itertools import *
import string
import time
That's the basic function, that is supposed to check, if a given password works or not:
def crack(File, pwd):
try:
File.extractall(pwd=str.encode(pwd))
print("\n---- SUCCESS! {0} ----".format(pwd))
except:
print("{0} did not work.".format(pwd))
pass
Here I specify, which characters I want to use for trying:
myLetters = string.ascii_letters
Here I specify, which zip-file I want to crack:
File = zipfile.ZipFile("PATH/TO/MY/zip3.zip", 'r')
Here I specify, how long the password-phrase is:
pwd_len = 3
here I specify, how many possible combinations of the charactes exist:
all_poss = (len(myLetters)**pwd_len)
Here is the procedure for concrete password cracking:
count = 0
start_time = time.time()
for i in range(0,pwd_len+1):
for j in map(''.join, itertools.product(myLetters, repeat=i)):
crack(File, j)
count += 1
print(round((count/all_poss)*100, 1), end='\r')
res_time = time.time() - start_time
print("\n--- {} ---".format(round(res_time,2)))
I use a nested loop, to try every password. If it works, I should get the Success-message. Else I should only see the "doesn't work message".
However...
If I type in my terminal: python3 pwdCracker.py >> out I get a long text file, which contains many many "does not work messages", BUT I also get a whole bunch of "Success-messages", although only ONE ("bla") should be correct.
Here is a little extract:
wN did not work.
---- SUCCESS! wO ----
wO did not work.
wP did not work.`
So apparently "wO" is working.. But why?? I set the password to "bla"! I really can open the file with "wO"... why can that happen??
Hope you can help!
The default zip encryption is known to be weak, and I think you are seeing hash collisions 1,2.
Most encryption methods (including those used in zip files) need a fixed length key, and so the password is hashed to give that key. The hash function used in zip is crc32 (specified here, although it details a different attack) which was designed for error checking rather than cryptographic hashing. Therefore it will be vulnerable to this type of attack.
The old zip format contains a check byte to quickly verify if your password is right or wrong. This check byte is verified against the last byte of the decrypted 'decryption header'.
Since the check byte is, well, only one byte, false positives happen quite frequently (1/256). What bruteforce crackers usually do in these cases is to check against multiple files from the same archive (hence using multiple check bytes).
From PkWare's APPNOTE.TXT:
After the header is decrypted, the last 1 or 2 bytes in Buffer SHOULD
be the high-order word/byte of the CRC for the file being decrypted,
stored in Intel low-byte/high-byte order. Versions of PKZIP prior to
2.0 used a 2 byte CRC check; a 1 byte CRC check is used on versions after 2.0.
This can be used to test if the password supplied is correct or not.
So what you are seeing is just that, false positives.

Hashing Password in .py file

how i said in the title, i want the password to be hashed when is saved. Its possible with this?
def __OnClickSaveLoginButton(self):
id = self.idEditLine.GetText()
pwd = self.pwdEditLine.GetText()
if (len(id) == 0 or len(pwd) == 0):
self.PopupNotifyMessage("ID and Password required",self.SetIDEditLineFocus)
return
file_object = open("account.cfg", "w")
file_object.write(id+"\n"+pwd)
self.PopupNotifyMessage("Saved.",self.SetIDEditLineFocus)
file_object.close()
You'll want to use the python hashlib. An example could look something like this:
import hashlib
def valid_password(userid, password):
user = get_user(userid)
pw_hash = hashlib.sha256(password).hexdigest()
if user.hash == pw_hash:
return True
return False
Also I recommend reviewing some password storage best practices noted in this SO
Edit: I used sh256 in this example, but that is more useful as a message digest. A better use would be hashlib.pbkdf2_hmac or another key derivation function. There is a good write up here.
If you're going to hash passwords in Python, as nudies mentioned, hashlib.pbkdf2_hmac is correct.
If you want to save the result in Base64, that's a reasonable option, as it turns it into a character string.
Just remember you also have to store the salt and the number of iterations; choose as high a number of iterations as your CPU can stand.
DO NOT request more bytes of output than the native hash function can support; for instance, PBKDF2-HMAC-SHA-512 caps out at 64 bytes for password hashing; the others less.
I have a fully working example at my github repository, including test vectors for all the normal SHA variants, of which the core piece is
import argparse,hashlib,base64,timeit
BinaryOutput = hashlib.pbkdf2_hmac('sha512',args.password, args.salt, args.iterations, args.outputBytes)
BinaryOutput.encode('base64')

Categories

Resources