SHA256 암호 크래커-v2 동시성

Nov 17 2020

제안 사항으로 이전 코드 를 업데이트했습니다 . 결과 속도를 높이기 위해 동시성을 구현했습니다.

동시성 / 병렬 처리 / 하이퍼 스레딩에 대한보다 효율적인 사용에 대한 의견이 필요합니다.

감사

import concurrent.futures
import hashlib
import time


def make_next_guess(guess):
    carry = 0
    next_guess = guess
    for i, char in enumerate(next_guess):
        if ord(char) >= ord("z"):
            carry = 1
            next_guess[i] = "!"
        elif ord(char) < ord("z"):
            next_guess[i] = chr(ord(char) + 1)
            carry = 0
        if carry == 0: break
    if carry:
        next_guess.append("!")
    return next_guess


def hash_password(pwrd):
    # Generates hash of original password
    try:
        pwrd = pwrd.encode("UTF-8")
        password = hashlib.sha256()
        password.update(pwrd)
        return password.hexdigest()
    except:
        pass


def find_password(secure_password, guess, integer):
    list_cracked = []
    # Brute force to find original password
    for _ in range(90 ** integer):  # password maximum length 14 and there are 58 characters that can be used
        return_password = "".join(guess)
        if hash_password(return_password) in secure_password:
            # print(f"Another password has been cracked: '{return_password}'")
            list_cracked.append(return_password)
        guess = make_next_guess(guess)
    return f"Finished cracking all passwords of length {integer}", list_cracked, integer


def rainbow_table_check(secure_password):
    global hash
    list_cracked = []
    for password in open("Rainbow.txt", "r", encoding="utf8"):
        try:
            password = password.strip()
            hash = hash_password(password)
        except:
            pass
        if hash in secure_password:
            # print(f"Another password has been cracked: {password}")
            list_cracked.append(password)
    return "Rainbow attack complete - passwords: ", list_cracked, "Rainbow"


def dic_attack(secure_password):
    list_cracked = []
    for password in open("Dic.txt", "r", encoding="utf8"):
        password = password.strip()
        lst = [password.lower(), password.upper(), password.title()]
        for password in lst:
            hash = hash_password(password)
            if hash in secure_password:
                # print(f"Another password has been cracked: {password}")
                list_cracked.append(password)
    return "Dictionary attack complete - passwords: ", list_cracked, "Dictionary"


if __name__ == "__main__":
    all_passwords = []
    start = time.time()
    secure_password = set()
    print("Attempting to crack passwords....")
    password_list = ["ABd", "Abc", "lpo", "J*&", "Njl", "!!!!", "Aqz", "Apple", "Cake", "Biden", "password1"]
    for password in password_list:
        secure_password.add(hash_password(password))
    with concurrent.futures.ProcessPoolExecutor() as executor:
        results = [executor.submit(dic_attack, secure_password),
                   executor.submit(rainbow_table_check, secure_password),
                   executor.submit(find_password, secure_password, ['!'], 1),
                   executor.submit(find_password, secure_password, ['!', '!'], 2),
                   executor.submit(find_password, secure_password, ['!', '!', '!'], 3),
                   executor.submit(find_password, secure_password, ['!', '!', '!', '!'], 4),
                   executor.submit(find_password, secure_password, ['!', '!', '!', '!', '!'], 5)]
        for f in concurrent.futures.as_completed(results):
            message, cracked, method = f.result()
            time_run = f"{round((time.time() - start) // 60)} min {round((time.time() - start) % 60)} sec"
            print(f"{message} : {cracked} - {time_run}")
            all_passwords += cracked
    print(f"Complete list of cracked passwords: {set(tuple(all_passwords))}")
    print(f"This operation took: {round((time.time() - start) // 60)} min {round((time.time() - start) % 60)} sec")

답변

1 RootTwo Nov 17 2020 at 07:35

두 가지 관찰 :

의 메소드는 hashlib바이트 수신 을 예상합니다. 에서는 문자열 대신 make_next_guess()a bytearray를 사용 합니다. 즉에 대한 호출 방지 ''.join(), ord(), ''.encode('UTF-8')함수에게 발생기 즉 수익률 추측을하면서도, 등 더 나은합니다.

루프 에서 else절을 사용하면 for i, byte in enumerate(guess):로직이 약간 단순화됩니다. 루프가 완료되면 else절이 실행됩니다. 그러나 a breakelse절을 건너 뜁니다 . 여기서 루프가 증가 할 바이트를 찾지 못하면 else 절이 추측 길이에 다른 바이트를 추가합니다.

다음과 같은 것 :

def generate_guesses(start):
    ORD_Z = ord('z')
    ORD_BANG = ord("!")
    
    guess = start[:]
    
    while True:
        yield guess
        for i, byte in enumerate(guess):
            if byte < ORD_Z:
                guess[i] += 1
                break
                
            else:
                guess[i] = ORD_BANG
                
        else:
            guess.append(ORD_BANG)

다음과 같이 부름 :

for guess in generate_guesses(bytearray(b'xzzzz')):
    ... do something with the guess ...

생성기가 중지되어야하는시기 또는 생성해야하는 추측 횟수를 알려주 는 stop또는 count인수를 추가 할 수 있습니다. while True:라인을 변경하여 정지 상태를 확인하십시오.

두 번째 관찰은 풀에 제출 된 마지막 작업이 이전 작업보다 90 배 더 많은 작업이라는 것입니다. 실제로 이전 4 개의 작업을 합친 것보다 더 많은 작업입니다 (다른 모든 작업 일 수도 있음). 결과적으로 다른 작업은 더 빨리 완료되고 하나의 작업은 한 프로세서 코어에서 오랫동안 실행됩니다. 모든 프로세서 코어를 계속 사용하려면 작업을 더 동일한 크기의 청크로 분할 해보십시오. 예를 들어 작업은 동일한 크기의 비밀번호 검색 공간 청크에서 작동 할 수 있습니다.

'!'    to 'zzz' 
'!!!!' to 'zzz!'
'!!!"' to 'zzz"'
'!!!#' to 'zzz#' these are all chunks of 729k (90*90*90) guesses
     ...
'!!!z' to 'zzzz'