SHA-1: The Successor That Also Failed
SHA-1: The Successor That Also Failed
SHA-1 (Secure Hash Algorithm 1) was developed by the NSA and published by NIST in 1995 as a more secure alternative to MD5. Producing 160-bit hashes (40 hexadecimal characters), SHA-1 offered better collision resistance through its larger output size and improved internal structure. The algorithm quickly gained widespread adoption, becoming mandatory for many U.S. government applications and integral to protocols like SSL/TLS.
Despite initial confidence in SHA-1's security, theoretical attacks emerged as early as 2005. Researchers found mathematical weaknesses reducing the complexity of finding collisions from the theoretical 2⁸⁰ operations to 2⁶⁹. While still computationally expensive, this reduction signaled SHA-1's eventual demise. The cryptographic community began transitioning away from SHA-1, but legacy systems and established protocols made complete migration challenging.
import hashlib
import itertools
import string
def sha1_vulnerability_demo():
"""Demonstrate SHA-1 speed and why it's vulnerable for passwords"""
# Show SHA-1 speed
password = "SecurePassword123!"
iterations = 1000000
start = time.time()
for _ in range(iterations):
hashlib.sha1(password.encode()).hexdigest()
elapsed = time.time() - start
print(f"SHA-1 Performance Test:")
print(f"Hashed '{password}' {iterations:,} times in {elapsed:.2f} seconds")
print(f"Rate: {iterations/elapsed:,.0f} hashes/second")
# Demonstrate dictionary attack feasibility
common_passwords = ['password', '123456', 'admin', 'letmein', 'welcome']
target_hash = hashlib.sha1("admin".encode()).hexdigest()
print(f"\nDictionary Attack Simulation:")
print(f"Target hash: {target_hash}")
for pwd in common_passwords:
if hashlib.sha1(pwd.encode()).hexdigest() == target_hash:
print(f"Password found: '{pwd}'")
break
# Show brute force potential
charset = string.ascii_lowercase
max_length = 4
print(f"\nBrute force potential (lowercase, max length {max_length}):")
total_combinations = sum(len(charset)**i for i in range(1, max_length+1))
time_to_crack = total_combinations / (iterations/elapsed)
print(f"Total combinations: {total_combinations:,}")
print(f"Time to test all: {time_to_crack:.2f} seconds")
sha1_vulnerability_demo()
The death knell for SHA-1 came in 2017 when Google and CWI Amsterdam announced SHAttered, the first practical SHA-1 collision. The attack required equivalent of 6,500 years of single-CPU computation, but only 110 years of single-GPU computation—achievable within reasonable budgets using cloud computing. This practical demonstration forced remaining holdouts to finally abandon SHA-1, though deprecated systems unfortunately continue using it for password hashing.