Selecting a part of the password by brute force attack (brute force attack) by mask and sha-256

I have a piece of the password *elp** (instead of asterisks, there should be characters to pick up), but I know from it sha256 hash:

fda23a72c73c92a1ad61cd18c58961b90c2c127028c8b87fd1a65c5e1f55d17e

I need to find a password for it from all this information (if anything, the password helpMe)

I wrote a piece of the program and I don't know how to do it further

import hashlib
mas = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","1","2","3","4","5","6","7","8","9","0"]

a = b'Hello'
sha = hashlib.sha256(a).hexdigest()

print(sha) 
Author: jfs, 2018-01-28

2 answers

Try this way:

import string    
import hashlib
from itertools import product

def brute_force(mask, hsh, alphabet=string.ascii_letters+string.digits, verbose=False):
    # экранируем фигурные скобки
    # и заменяем '*' на '{}' для последующей подстановки в 'str.format()'
    pwd_pat = mask.replace('{', '{{').replace('}','}}').replace('*', '{}')
    # число звездочек - будем использовать в качестве `product(.., repeat)`
    N = mask.count('*')
    i = 0
    for chars in product(alphabet, repeat=N):
        if verbose:
            i += 1
            if i % 10000 == 0:
                print('Iterations: {}'.format(i))
        if hsh == hashlib.sha256(pwd_pat.format(*chars).encode()).hexdigest():
            return pwd_pat.format(*chars)
    return None

Test:

hsh = 'fda23a72c73c92a1ad61cd18c58961b90c2c127028c8b87fd1a65c5e1f55d17e'

In [245]: brute_force('*elp**', hsh, verbose=True)
Iterations: 10000
Iterations: 20000
Out[245]: 'helpMe'
 7
Author: MaxU, 2018-01-29 12:55:19

A variant that works with bytes and uses all available CPUs:

#!/usr/bin/env python3
import hashlib
import itertools
import multiprocessing
import string
from functools import partial

alphabet = string.ascii_lowercase.encode()


def sha256(data):
    return hashlib.sha256(data).digest()


def check_sha256(repls_parent, bytes_format, n, target_sha256):
    for repls in itertools.product(alphabet, repeat=n):
        data = bytes_format % (repls_parent + repls)
        if sha256(data) == target_sha256:
            return data


def brute_force(mask, target_sha256, n_cutoff=4):
    """
    n_cutoff -- number of `*` to process in a worker process
    """
    bytes_format = mask.replace(b'%', b'%%').replace(b'*', b'%c')
    mp_check = partial(check_sha256,
                       bytes_format=bytes_format,
                       n=min(n_cutoff, mask.count(b'*')),
                       target_sha256=target_sha256)
    n = max(0, mask.count(b'*') - n_cutoff)
    all_repls_parent = itertools.product(alphabet, repeat=n)
    with multiprocessing.Pool() as pool:
        for data in pool.imap_unordered(mp_check, all_repls_parent):
            if data is not None:
                return data

Example:

import binascii

sha256_hex = b'c4bbcb1fbec99d65bf59d85c8cb62ee2db963f0fe106f483d9afa73bd4e39a8a'
passw_bytes = brute_force(b'******t horse battery staple',
                          binascii.unhexlify(sha256_hex))
print(passw_bytes.decode())

The task is parallelized by delegating the generation of n_cutoff substitutions to child processes. The task is suitable for GPU computing. Because of the sha256 connection with Bitcoin mining, there are ASICs that are sharpened for calculating hashes.

To track your progress, you can tqdm module use:

from tqdm import tqdm

#...
all_repls_parent = itertools.product(alphabet, repeat=n)
with multiprocessing.Pool() as pool:
    for data in tqdm(pool.imap_unordered(mp_check, all_repls_parent),
                     total=len(alphabet)**n):
        if data is not None:
            return data
 3
Author: jfs, 2018-01-29 10:03:23