SHA256 암호 크래커-v2 동시성
제안 사항으로 이전 코드 를 업데이트했습니다 . 결과 속도를 높이기 위해 동시성을 구현했습니다.
동시성 / 병렬 처리 / 하이퍼 스레딩에 대한보다 효율적인 사용에 대한 의견이 필요합니다.
감사
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")
답변
두 가지 관찰 :
의 메소드는 hashlib
바이트 수신 을 예상합니다. 에서는 문자열 대신 make_next_guess()
a bytearray
를 사용 합니다. 즉에 대한 호출 방지 ''.join()
, ord()
, ''.encode('UTF-8')
함수에게 발생기 즉 수익률 추측을하면서도, 등 더 나은합니다.
루프 에서 else
절을 사용하면 for i, byte in enumerate(guess):
로직이 약간 단순화됩니다. 루프가 완료되면 else
절이 실행됩니다. 그러나 a break
는 else
절을 건너 뜁니다 . 여기서 루프가 증가 할 바이트를 찾지 못하면 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'