Created
January 22, 2021 01:09
-
-
Save anax32/a596d0ce65fd27c9cfbd12b4cc74bd4e to your computer and use it in GitHub Desktop.
Example brute force attack against SHA key
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Attempt brute force attack against an SHA256 encrypted value | |
The length of the key can be chosen as script parameter and | |
demonstrates how key length is crucial to security of the key. | |
run the script with a 6 bit private key: | |
> python brute.py 6 | |
compare with a 12 bit private key: | |
> python brute.py 12 | |
waste electricity with a 64 bit private key: | |
> python brute.py 64 | |
""" | |
import hashlib | |
import random | |
from time import perf_counter as clock | |
def gen_key(key_length=256): | |
""" | |
generate a number as a random string and convert to bytes | |
key_length: number of bits in the key | |
""" | |
b = [int(random.uniform(0, 1) > 0.5) | |
for _ in range(key_length)] | |
k = sum(e << i for i, e in enumerate(b)) | |
return k | |
# | |
# search stragegies | |
# | |
def ordered_value_generator(key_length): | |
""" | |
generate a sequence of values from 0 to 2^key_length | |
""" | |
for i in range(2**key_length): | |
yield i | |
def random_value_generator(key_length): | |
""" | |
generate 2^key_length random numbers in the range 0 to 2^key_length | |
NB: likely to generate collisions and not have full coverage | |
""" | |
for _ in range(2**key_length): | |
yield random.randrange(2**key_length) | |
def search(key_length, hash_fn, values): | |
""" | |
explore the search space by hashing data from values | |
and yield the input and hashed value as a tuple | |
""" | |
for i in values: | |
yield i, hash_fn(str(i).encode()) | |
if __name__ == "__main__": | |
import sys | |
key_length = 12 if len(sys.argv) < 2 else int(sys.argv[1]) | |
print("space : %i [2^%i] possible key values" % (2**key_length, key_length)) | |
# generate a random key | |
key = gen_key(key_length) | |
print("value : %i" % key) | |
# find the original value from the hash | |
hash_fn = lambda x: hashlib.sha256(x).hexdigest() | |
target = hash_fn(str(key).encode()) | |
compare = lambda x, y: x == y | |
print("hash : %s" % target) | |
T0 = clock() | |
hash_count = 0 | |
for q, candidate in search( | |
key_length, | |
hash_fn=hash_fn, | |
# values = random_value_generator(key_length)): | |
values = ordered_value_generator(key_length)): | |
hash_count += 1 | |
msg = "\r%s: %s" % (str(q).zfill(key_length), candidate) | |
sys.stdout.write(msg) | |
sys.stdout.flush() | |
if compare(candidate, target) is True: | |
T1 = clock() | |
break | |
print("\nfound: %i in %0.8fs [%ikh/s]" % (q, T1-T0, int(hash_count/(T1-T0))/1000)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment