How to Crack Hashes in Python

Learn how to crack hashes using Python's hashlib library and a brute-force approach with a wordlist. Gain insights into various hashing algorithms and understand the importance of secure data handling.
  · 5 min read · Updated feb 2024 · Ethical Hacking · Cryptography

Unlock the secrets of your code with our AI-powered Code Explainer. Take a look!

Cryptographic hashes are a fundamental part of modern cybersecurity. They are used to securely store and verify data, especially passwords. However, understanding how they can be compromised is also essential for protecting systems.

In this tutorial, we'll explore a simple Python script that demonstrates a brute-force approach to cracking cryptographic hashes with a wordlist using the hashlib library in Python. The technique tries all possible words from a list to find the original input that produced the hash.

Please note that this tutorial is for educational purposes only and should not be used for malicious activities. Understanding these concepts is crucial for building secure systems, but misuse of this information can lead to legal consequences.

Build 39 Ethical Hacking Scripts & Tools with Python EBook

To get started, let's install the tqdm library for showing progress bars:

$ pip install tqdm

Open up a new Python file named crack_hashes.py for instance, and add the following:

import hashlib
from tqdm import tqdm

# List of supported hash types
hash_names = [
    'blake2b', 
    'blake2s', 
    'md5', 
    'sha1', 
    'sha224', 
    'sha256', 
    'sha384', 
    'sha3_224', 
    'sha3_256', 
    'sha3_384', 
    'sha3_512', 
    'sha512',
]

We defined a list of hashing algorithms that are supported by hashlib. Now let's make the cracking function:

def crack_hash(hash, wordlist, hash_type=None):
    """Crack a hash using a wordlist.
    Args:
        hash (str): The hash to crack.
        wordlist (str): The path to the wordlist.
    Returns:
        str: The cracked hash."""
    hash_fn = getattr(hashlib, hash_type, None)
    if hash_fn is None or hash_type not in hash_names:
        # not supported hash type
        raise ValueError(f'[!] Invalid hash type: {hash_type}, supported are {hash_names}')
    # Count the number of lines in the wordlist to set the total
    total_lines = sum(1 for line in open(wordlist, 'r'))
    print(f"[*] Cracking hash {hash} using {hash_type} with a list of {total_lines} words.")
    # open the wordlist
    with open(wordlist, 'r') as f:
        # iterate over each line
        for line in tqdm(f, desc='Cracking hash', total=total_lines):
            if hash_fn(line.strip().encode()).hexdigest() == hash:
                return line

The above function takes three parameters: The actual target hash to crack, the wordlist filename, and the hash type (whether it's MD5, SHA-1, SHA256, etc.):

  • First, we verify whether the target hash_type is supported by hashlib and within our list. If it is supported, then hash_fn will contain the hashing function. If not, we simply raise a ValueError indicating that the hash type is invalid.
  • Second, we perform a preliminary pass through the wordlist file to count the number of lines and then set that in the total_lines variable so we can pass it to the total parameter in tqdm().
  • And finally, we open up the wordlist file, iterate through it (by wrapping tqdm for printing the progress bar), and hash each line to compare it with the target hash. If it's equal, we return that word (and so we have found the password).

Get Our Ethical Hacking with Python EBook

Master Ethical Hacking with Python by building 35+ Tools from scratch. Get your copy now!

Download EBook

Now that we have the responsible function, let's use argparse to parse the command-line arguments passed by the user:

if __name__ == "__main__":
    import argparse
    parser = argparse.ArgumentParser(description='Crack a hash using a wordlist.')
    parser.add_argument('hash', help='The hash to crack.')
    parser.add_argument('wordlist', help='The path to the wordlist.')
    parser.add_argument('--hash-type', help='The hash type to use.', default='md5')
    args = parser.parse_args()
    print()
    print("[+] Found password:", crack_hash(args.hash, args.wordlist, args.hash_type))

So hash and wordlist are required parameters, and --hash-type is set to MD5 by default (if nothing is passed).

Before we run the script, let's make up a target hash to crack. I'm doing that in an interactive Python shell:

>>> import hashlib
>>> hashlib.sha256(b"abc123")
<sha256 _hashlib.HASH object @ 0x00000123B881FF50>
>>> hashlib.sha256(b"abc123").hexdigest()
'6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090'
>>> exit()

The hashing function returns a hash object, so we need to call hexdigest() function to get it as str.

I'm also using the RockYou wordlist (about 135MB) which contains more than 14 million passwords, I've also moved my toy abc123 password to the end of the file. You can use any wordlist you want.

Let's run the script now:

$ python crack_hashes.py 6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090 rockyou.txt --hash-type sha256
[*] Cracking hash 6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090 using sha256 with a list of 14344394 words.
Cracking hash:  96%|███████████████████████████████████████████████████████████████████████████████████████████▉    | 13735317/14344394 [00:20<00:00, 664400.58it/s]
[+] Found password: abc123

Notice I passed the hash first, then the wordlist name, then the hash type. Amazing! It took about 20 seconds to run through the RockYou password list and finally found it! The speed is quite impressive (about ~660,000 iterations per second) given that it's Python and only one laptop CPU core.

For more information about hashes, I suggest you check this tutorial of ours.

Conclusion

Alright, we're done with this quick tutorial, where we provided a simple and educational insight into the world of cryptographic hashes and how we can perform brute-force on them. While this is a basic example, it is a good starting point for understanding the principles of hashing and security.

Get the complete code here.

Finally, in our Ethical Hacking with Python EBook, we've built more than 39 hacking tools and scripts from scratch using Python! Check it out here if you're interested! Also, if you're more into cryptography, we have a detailed eBook about that as well; check it out here.

Learn also: How to Use Hashing Algorithms in Python

Happy coding ♥

Save time and energy with our Python Code Generator. Why start from scratch when you can generate? Give it a try!

View Full Code Auto-Generate My Code
Sharing is caring!



Read Also



Comment panel

    Got a coding query or need some guidance before you comment? Check out this Python Code Assistant for expert advice and handy tips. It's like having a coding tutor right in your fingertips!