Crpyto-HW7/part1.py
2025-11-25 16:01:49 -06:00

166 lines
4.9 KiB
Python

import hashlib
import itertools
import time
import string
# Define character set: 0-9, a-z, A-Z, and special symbols
CHARACTERS = string.digits + string.ascii_lowercase + string.ascii_uppercase + '#$%^&*'
def generate_sha256_hash(password):
"""Generate SHA256 hash of a password."""
return hashlib.sha256(password.encode()).hexdigest()
def read_password_database(filename):
"""
Read password database from a text file.
Args:
filename: Path to the file containing [username, hash] pairs
Returns:
List of [username, hash] pairs
"""
database = []
try:
with open(filename, 'r') as f:
for line in f:
line = line.strip()
if line and line.startswith('[') and line.endswith(']'):
# Remove brackets and split by comma
content = line[1:-1]
parts = content.split(',', 1) # Split only on first comma
if len(parts) == 2:
username = parts[0].strip()
password_hash = parts[1].strip()
database.append([username, password_hash])
print(f"Loaded {len(database)} accounts from {filename}")
return database
except FileNotFoundError:
print(f"Error: File '{filename}' not found.")
return []
except Exception as e:
print(f"Error reading file: {e}")
return []
def dictionary_attack(password_database, N):
"""
Perform dictionary attack on password database.
Args:
password_database: List of [username, hash] pairs
N: Length of passwords to try
Returns:
Dictionary mapping usernames to cracked passwords
Time taken for the attack
"""
print(f"\n{'='*60}")
print(f"Starting Dictionary Attack")
print(f"Password length: {N}")
print(f"Character set size: {len(CHARACTERS)}")
print(f"Total possible passwords: {len(CHARACTERS)**N}")
print(f"Number of accounts to crack: {len(password_database)}")
print(f"{'='*60}\n")
# Create a dictionary of hash -> username for faster lookup
hash_to_user = {entry[1]: entry[0] for entry in password_database}
cracked_passwords = {}
start_time = time.time()
attempts = 0
# Generate all possible passwords of length N
for password_tuple in itertools.product(CHARACTERS, repeat=N):
password = ''.join(password_tuple)
attempts += 1
# Hash the password
password_hash = generate_sha256_hash(password)
# Check if this hash matches any in the database
if password_hash in hash_to_user:
username = hash_to_user[password_hash]
cracked_passwords[username] = password
print(f"[+] Cracked! {username}: {password}")
# If all passwords are cracked, we can stop
if len(cracked_passwords) == len(password_database):
break
# Progress indicator (every 10000 attempts for small N, adjust as needed)
if attempts % 10000 == 0:
print(f"Tried {attempts} passwords...")
end_time = time.time()
time_taken = end_time - start_time
print(f"\n{'='*60}")
print(f"Attack Complete!")
print(f"Time taken: {time_taken:.4f} seconds")
print(f"Total attempts: {attempts}")
print(f"Passwords cracked: {len(cracked_passwords)}/{len(password_database)}")
print(f"{'='*60}\n")
return cracked_passwords, time_taken
def main():
"""Main function to run the dictionary attack demonstration."""
print("Dictionary Attack on SHA256 Password Hashes")
print("=" * 60)
# Get input file and password length from user
filename = input("Enter password database filename: ")
N = int(input("Enter password length N: "))
# Warn if N is too large
if N > 4:
total_passwords = len(CHARACTERS) ** N
print(f"\nWarning: With N={N}, there are {total_passwords:,} possible passwords.")
print("This may take a very long time!")
confirm = input("Continue? (yes/no): ")
if confirm.lower() != 'yes':
print("Attack cancelled.")
return
# Read password database from file
print("\nReading password database...")
password_database = read_password_database(filename)
if not password_database:
print("No valid data found. Exiting.")
return
print("\nPassword Database:")
for username, password_hash in password_database:
print(f"[{username}, {password_hash}]")
# Perform dictionary attack
cracked_passwords, time_taken = dictionary_attack(password_database, N)
# Display results
print("\nResults:")
for username, password in cracked_passwords.items():
print(f"{username}: {password}")
print(f"\nTotal time: {time_taken:.4f} seconds")
if __name__ == "__main__":
main()