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.