SHA-256 哈希破解工具技术解析
一、程序功能概述
一个针对 SHA-256 哈希值的密码破解工具,其核心功能是通过多种密码攻击技术,将给定的 SHA-256 哈希值反向还原为原始明文密码。该工具集成了字典攻击、模式攻击、暴力破解等多种方法,通过组合不同的攻击策略提高哈希破解的成功率,适用于安全测试、密码审计等场景(需在合法授权范围内使用)。
程序的核心目标是:接收包含多个 SHA-256 哈希值的文件(默认1.txt),通过内置的密码生成与验证逻辑,找到哈希值对应的原始密码,并将结果保存到输出文件(默认2.txt)。其功能覆盖了从数据加载、密码生成、哈希比对到结果保存的完整流程,同时包含进度跟踪与状态提示,提升用户对破解过程的感知。
二、核心数据结构解析
程序通过HashCracker类封装所有功能,类内定义了多个关键数据结构,用于存储状态、配置与结果,这些结构的设计直接影响破解效率与功能完整性。
1. 实例属性设计
| 属性名 | 类型 | 作用 | 设计逻辑 |
|---|---|---|---|
found_passwords | 字典(dict) | 存储已破解的哈希值与对应密码,键为哈希值,值为明文密码 | 字典的键值对结构支持 O (1) 时间复杂度的哈希值查找,避免重复破解同一哈希 |
common_passwords | 列表(list) | 存储常用密码字典,用于字典攻击 | 列表适合按顺序遍历,且支持随机访问,便于后续对密码进行变体生成 |
total_hashes | 整数(int) | 记录需要破解的哈希值总数 | 用于进度计算,提升用户对破解过程的感知 |
cracked_count | 整数(int) | 记录已成功破解的哈希值数量 | 与total_hashes配合,实时展示破解进度,同时作为提前终止攻击的判断依据 |
2. 辅助数据结构
- 哈希值集合:在攻击方法中,程序将加载的哈希值列表转换为隐含的集合结构(通过
in操作判断),利用集合的 O (1) 成员检测特性,快速验证生成的密码哈希是否在目标列表中,大幅提升比对效率。 - 变体生成器:在
dictionary_with_variations和advanced_variations方法中,通过 lambda 表达式列表、字符串列表(如特殊字符、数字)定义密码变体规则,这些列表结构便于扩展变体类型,只需添加新元素即可增加变体策略。 - 模式库:
common_patterns方法中使用列表存储键盘模式、年份、月份等常见密码模式,列表的顺序性支持按优先级遍历(如先检测基础模式,再检测带数字的变体)。
三、核心算法与攻击策略详解
程序集成了 5 种核心攻击算法,覆盖了从简单到复杂的密码破解场景,通过逐步提升攻击复杂度,最大化破解成功率。
1. 基础字典攻击(basic_dictionary_attack)
算法原理
基于 “多数用户使用常见密码” 的假设,直接使用预设的常用密码字典(如rockyou.txt或内置字典),计算每个密码的 SHA-256 哈希值,与目标哈希值比对,若匹配则记录结果。
实现逻辑
def basic_dictionary_attack(self, hashes): for password in self.common_passwords: hash_value = self.sha256_hash(password) if hash_value in hashes and hash_value not in self.found_passwords: self.found_passwords[hash_value] = password self.cracked_count += 1 print(f"破解成功: {password}") 关键细节
- 依赖
common_passwords列表,该列表通过load_rockyou方法加载,若rockyou.txt不存在则使用内置的 15 个常见密码(如123456、password)。 - 每次比对前检查
hash_value是否已在found_passwords中,避免重复计算与存储,优化性能。 - 时间复杂度:O (N),其中 N 为字典中密码的数量,哈希计算为常数时间操作。
2. 常见模式攻击(common_patterns)
算法原理
针对用户密码中常见的 “模式化特征”(如键盘连续字符、年份、季节、颜色等),预定义模式库,生成对应密码并验证哈希。
实现逻辑
def common_patterns(self, hashes): # 预定义模式库 patterns = [ 'qwerty', 'asdfgh', # 键盘模式 '1980', '1981', ..., '2024', # 年份 'january', ..., 'december', # 月份 'red', 'blue', ... # 颜色 ] # 验证基础模式 for pattern in patterns: hash_value = self.sha256_hash(pattern) if hash_value in hashes and hash_value not in self.found_passwords: # 记录结果 # 验证带数字的模式变体 for pattern in patterns: for i in range(10): variant = pattern + str(i) # 计算哈希并比对 关键细节
- 模式库分类明确,覆盖键盘规律(
qwerty)、时间相关(年份、月份)、常见词汇(颜色、季节)等,贴合用户设置密码的习惯。 - 分两步验证:先验证基础模式,再验证带数字后缀的变体(如
qwerty1),逐步扩展覆盖范围。 - 优势:无需依赖外部字典,通过人工总结的模式即可破解部分密码,适用于字典攻击失效的场景。
3. 带变体的字典攻击(dictionary_with_variations)
算法原理
基于 “用户常对基础密码进行简单变形” 的行为特征(如加数字后缀、特殊字符、大小写转换等),对字典中的密码生成变体,扩大密码覆盖范围。
实现逻辑
def dictionary_with_variations(self, hashes): # 定义变体规则(lambda表达式列表) common_variations = [ lambda p: p + '1', lambda p: p + '123', # 加数字 lambda p: p + '!', lambda p: p + '@', # 加特殊字符 lambda p: p.capitalize(), lambda p: p.upper(), # 大小写转换 ... ] # 对字典前10000个密码生成变体 for password in self.common_passwords[:10000]: for variation in common_variations: try: variant = variation(password) hash_value = self.sha256_hash(variant) # 比对哈希并记录结果 except: continue 关键细节
- 变体规则设计:包含 15 种常见变形,如加数字(
1、123)、加特殊字符(!、@)、年份后缀(2020-2024)、大小写转换等,覆盖用户常见的密码修改习惯。 - 性能优化:限制处理前 10000 个密码(
self.common_passwords[:10000]),避免因字典过大导致耗时过长。 - 异常处理:通过
try-except捕获变体生成中的错误(如特殊字符处理问题),保证程序稳定性。
4. 简单暴力破解(brute_force_simple)
算法原理
通过穷举所有可能的字符组合生成密码,计算哈希值并比对。由于暴力破解复杂度极高,程序仅针对短密码(默认长度≤4)进行尝试。
实现逻辑
def brute_force_simple(self, hashes, max_length=4): chars = string.ascii_lowercase + string.digits # 字符集:小写字母+数字 for length in range(1, max_length + 1): # 生成所有长度为length的字符组合 for combo in itertools.product(chars, repeat=length):.join(combo) hash_value = self.sha256_hash(password) # 比对哈希并记录结果 关键细节
- 字符集设计:仅包含小写字母(26 个)和数字(10 个),共 36 个字符,减少穷举范围(若包含大写字母和特殊字符,复杂度会急剧上升)。
- 长度限制:默认最大长度为 4,此时可能的组合数为 36^1 + 36^2 + 36^3 + 36^4 = 36 + 1296 + 46656 + 1679616 = 1727604 种,计算量可控;若长度增加到 5,组合数会增至 62193816,耗时显著上升。
- 工具依赖:使用
itertools.product生成笛卡尔积,高效创建字符组合,避免手动嵌套循环的冗余代码。
5. 高级变体攻击(advanced_variations)
算法原理
在基础变体攻击的基础上,对核心词根进行更复杂的变形组合(如词根 + 数字 + 特殊字符、大小写混合、词根重复等),覆盖更复杂的密码结构。
实现逻辑
def advanced_variations(self, hashes): base_words = ['love', 'god', 'life', ...] # 基础词根 special_chars = ['!', '@', '#', ...] # 特殊字符 numbers = ['', '1', '123', ...] # 数字后缀 for word in base_words: # 生成基础变体(原词、首字母大写、全大写、重复词根) variants = [word, word.capitalize(), word.upper(), word + word] # 添加数字后缀变体 for num in numbers: variants.extend([word + num, word.capitalize() + num]) # 添加特殊字符变体(前加、后加、加数字组合) for char in special_chars: variants.extend([ word + char, char + word, word.capitalize() + char, char + word.capitalize(), word + char + '1', word + char + '123' ]) # 验证所有变体 for variant in variants: # 计算哈希并比对 关键细节
- 词根选择:选取
love、god、life等具有情感或常用意义的词根,符合用户用有意义词汇作为密码基础的习惯。 - 变体组合:通过 “词根 + 数字”“词根 + 特殊字符”“特殊字符 + 词根”“词根 + 特殊字符 + 数字” 等多层组合,生成更复杂的变体(如
Love!123、#life200),覆盖用户对密码安全性的基础优化行为。 - 灵活性:通过扩展
base_words、special_chars或numbers列表,可轻松增加变体类型,适应不同场景的密码特征。
四、程序执行流程解析
程序通过crack_hashes方法作为主入口,串联数据加载、攻击执行、结果保存等环节,形成完整的破解流程。
1. 初始化与数据加载阶段
- 哈希值加载:通过
load_hashes方法读取目标哈希文件(默认1.txt),每行提取一个哈希值并去除空白字符,存储为列表,同时记录total_hashes(哈希总数)。 - 密码字典加载:通过
load_rockyou方法加载外部字典文件rockyou.txt(著名的密码泄露字典),若文件不存在则调用get_builtin_common_passwords使用内置的 15 个常见密码,结果存储到common_passwords列表。
2. 攻击方法执行阶段
程序按优先级顺序执行 5 种攻击方法,通过cracked_count判断是否已破解所有哈希,若完成则提前终止:
- 基础字典攻击:优先使用原始字典密码,快速破解简单密码。
- 常见模式攻击:利用预设模式库,破解符合特定规律的密码。
- 带变体的字典攻击:对字典密码生成简单变体,覆盖用户的基础修改行为。
- 简单暴力破解:穷举短密码,应对无规律的简单密码。
- 高级变体攻击:通过复杂变体组合,破解经过一定优化的密码。
每个方法执行后,程序会输出耗时(通过time.time()计算)和当前进度(cracked_count/total_hashes),提升用户体验。
3. 结果保存与展示阶段
- 结果保存:
save_results方法将所有哈希值与对应破解结果(若存在)写入2.txt,格式为 “哈希值:密码”。 - 结果展示:主函数
main中输出前 10 条破解结果,便于用户快速查看。
五、技术特点与优化策略
1. 多策略组合攻击
程序未依赖单一攻击方法,而是通过 “字典攻击→模式攻击→变体攻击→暴力破解” 的渐进式策略,兼顾效率与覆盖范围:
- 前期方法(字典、模式)效率高,适合快速破解简单密码;
- 后期方法(变体、暴力)复杂度高,用于破解更复杂的密码。
2. 性能优化设计
- 哈希值去重:通过
found_passwords字典自动过滤已破解的哈希值,避免重复计算。 - 范围限制:暴力破解限制最大长度(默认 4),变体攻击限制字典数量(前 10000 个),平衡破解效果与耗时。
- 高效数据结构:使用字典存储结果、集合进行哈希比对,保证核心操作(查找、比对)的时间复杂度为 O (1)。
3. 容错与兼容性处理
- 字典文件容错:
load_rockyou方法处理FileNotFoundError,自动切换为内置字典,避免程序崩溃。 - 编码容错:加载
rockyou.txt时使用errors='ignore'忽略无效编码字符,适应不同编码格式的字典文件。 - 异常捕获:变体生成过程中使用
try-except捕获错误,保证程序稳定性。
六、局限性与改进方向
1. 现有局限性
- 暴力破解能力弱:仅支持长度≤4 的小写字母 + 数字组合,无法破解更长或包含大写字母 / 特殊字符的密码。
- 无多线程支持:虽导入
threading模块,但未实现多线程并行计算,破解效率受单线程性能限制。 - 变体规则固定:变体生成依赖预设规则,无法自适应学习新的密码模式(如近期流行的密码结构)。
- 字典依赖度高:若
rockyou.txt不存在,内置字典规模过小(仅 15 个密码),影响基础字典攻击效果。
2. 潜在改进方向
- 引入多线程 / 多进程:将不同攻击方法或密码生成任务分配到多个线程 / 进程,利用多核 CPU 提升效率。
- 优化暴力破解:支持自定义字符集与长度范围,通过优先级队列动态调整破解顺序(如先尝试概率更高的字符组合)。
- 自适应变体生成:基于已破解密码的特征(如常见变体模式)动态调整变体规则,提升针对性。
- 集成 rainbow table:预计算常见密码的哈希值并存储,通过查表替代实时计算,大幅提升字典攻击效率。
- 进度持久化:支持中断后恢复进度,避免因程序退出导致重复计算。
七、总结
作为一款 SHA-256 哈希破解工具,通过组合多种攻击策略,实现了对不同复杂度密码的破解能力。其核心优势在于多方法协同、高效的数据结构设计与友好的进度反馈,适合作为密码安全审计的辅助工具。
程序的设计思路体现了密码破解的经典方法论:从简单到复杂,从概率高到概率低,逐步提升攻击强度。同时,其模块化的结构(分离加载、攻击、保存功能)便于扩展新的攻击方法或优化现有逻辑。
需注意的是,哈希破解技术应严格在合法授权范围内使用,用于保护系统安全而非恶意攻击。在实际应用中,还需结合目标密码的特征(如长度、复杂度)选择合适的攻击策略,平衡效率与成功率。
源代码:
import hashlib import itertools import string from collections import defaultdict import threading import time class HashCracker: def __init__(self): self.found_passwords = {} self.common_passwords = [] self.total_hashes = 0 self.cracked_count = 0 def load_hashes(self, filename): """加载哈希文件""" with open(filename, 'r') as f: hashes = [line.strip() for line in f if line.strip()] self.total_hashes = len(hashes) return hashes def load_rockyou(self, filename='rockyou.txt'): """加载rockyou密码字典""" common_passwords = [] try: with open(filename, 'r', encoding='utf-8', errors='ignore') as f: for line in f: password = line.strip() if password: common_passwords.append(password) print(f"成功加载 {len(common_passwords)} 个常用密码") except FileNotFoundError: print(f"未找到 {filename} 文件") # 如果没有rockyou.txt,使用内置的常见密码 common_passwords = self.get_builtin_common_passwords() return common_passwords def get_builtin_common_passwords(self): """内置的常见密码列表""" return [ '123456', 'password', '12345678', 'qwerty', 'abc123', '123456789', '111111', '1234567', 'iloveyou', 'admin', 'welcome', 'monkey', '1234567890', '123123', '000000' ] def sha256_hash(self, text): """计算SHA-256哈希值""" return hashlib.sha256(text.encode('utf-8')).hexdigest() def basic_dictionary_attack(self, hashes): """基础字典攻击""" print("开始基础字典攻击...") for password in self.common_passwords: hash_value = self.sha256_hash(password) if hash_value in hashes and hash_value not in self.found_passwords: self.found_passwords[hash_value] = password self.cracked_count += 1 print(f"破解成功: {password}") def dictionary_with_variations(self, hashes): """带变体的字典攻击""" print("开始带变体的字典攻击...") common_variations = [ lambda p: p + '1', lambda p: p + '12', lambda p: p + '123', lambda p: p + '!', lambda p: p + '@', lambda p: p + '#', lambda p: p + '2020', lambda p: p + '2021', lambda p: p + '2022', lambda p: p + '2023', lambda p: p + '2024', lambda p: p.capitalize(), lambda p: p.upper(), lambda p: p + '?', lambda p: '1' + p ] for password in self.common_passwords[:10000]: # 限制数量以避免过长时间 for variation in common_variations: try: variant = variation(password) hash_value = self.sha256_hash(variant) if hash_value in hashes and hash_value not in self.found_passwords: self.found_passwords[hash_value] = variant self.cracked_count += 1 print(f"破解成功: {variant}") except: continue def brute_force_simple(self, hashes, max_length=4): """简单暴力破解(短密码)""" print(f"开始简单暴力破解(长度≤{max_length})...") chars = string.ascii_lowercase + string.digits for length in range(1, max_length + 1): for combo in itertools.product(chars, repeat=length):.join(combo) hash_value = self.sha256_hash(password) if hash_value in hashes and hash_value not in self.found_passwords: self.found_passwords[hash_value] = password self.cracked_count += 1 print(f"破解成功: {password}") def common_patterns(self, hashes): """常见模式攻击""" print("开始常见模式攻击...") patterns = [ # 键盘模式 'qwerty', 'asdfgh', 'zxcvbn', '123qwe', '1qaz2wsx', # 常见单词 'password', 'admin', 'welcome', 'login', 'letmein', 'master', 'sunshine', 'princess', 'qwertyuiop', # 年份 '1980', '1981', '1982', '1983', '1984', '1985', '1986', '1987', '1988', '1989', '1990', '1991', '1992', '1993', '1994', '1995', '1996', '1997', '1998', '1999', '2000', '2001', '2002', '2003', '2004', '2005', '2006', '2007', '2008', '2009', '2010', '2011', '2012', '2013', '2014', '2015', '2016', '2017', '2018', '2019', '2020', '2021', '2022', '2023', '2024', # 月份 'january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december', # 季节 'spring', 'summer', 'autumn', 'winter', # 颜色 'red', 'blue', 'green', 'yellow', 'black', 'white', 'orange', 'purple' ] # 测试基本模式 for pattern in patterns: hash_value = self.sha256_hash(pattern) if hash_value in hashes and hash_value not in self.found_passwords: self.found_passwords[hash_value] = pattern self.cracked_count += 1 print(f"破解成功: {pattern}") # 测试带数字的模式 for pattern in patterns: for i in range(10): variant = pattern + str(i) hash_value = self.sha256_hash(variant) if hash_value in hashes and hash_value not in self.found_passwords: self.found_passwords[hash_value] = variant self.cracked_count += 1 print(f"破解成功: {variant}") def advanced_variations(self, hashes): """高级变体攻击""" print("开始高级变体攻击...") base_words = ['love', 'god', 'life', 'hello', 'test', 'demo', 'user', 'pass'] special_chars = ['!', '@', '#', '$', '%', '&', '*'] numbers = ['', '1', '12', '123', '1234', '12345', '007', '100', '200'] for word in base_words: # 大小写变体 variants = [ word, word.capitalize(), word.upper(), word + word, ] # 添加数字 for num in numbers: variants.extend([word + num, word.capitalize() + num]) # 添加特殊字符 for char in special_chars: variants.extend([ word + char, char + word, word.capitalize() + char, char + word.capitalize(), word + char + '1', word + char + '123' ]) for variant in variants: hash_value = self.sha256_hash(variant) if hash_value in hashes and hash_value not in self.found_passwords: self.found_passwords[hash_value] = variant self.cracked_count += 1 print(f"破解成功: {variant}") def save_results(self, hashes, filename='2.txt'): """保存结果到文件""" with open(filename, 'w', encoding='utf-8') as f: for hash_value in hashes: if hash_value in self.found_passwords: f.write(f"{hash_value}:{self.found_passwords[hash_value]}\n") print(f"\n结果已保存到 {filename}") print(f"总共破解了 {self.cracked_count}/{self.total_hashes} 个哈希") def crack_hashes(self, hash_file): """主破解函数""" print("开始破解SHA-256哈希...") # 加载数据 hashes = self.load_hashes(hash_file) self.common_passwords = self.load_rockyou() print(f"需要破解 {len(hashes)} 个哈希值") # 按顺序执行各种攻击方法 methods = [ self.basic_dictionary_attack, self.common_patterns, self.dictionary_with_variations, self.brute_force_simple, self.advanced_variations ] for method in methods: if self.cracked_count >= self.total_hashes: break start_time = time.time() method(hashes) end_time = time.time() print(f"{method.__name__} 完成,用时: {end_time - start_time:.2f}秒") print(f"当前破解进度: {self.cracked_count}/{self.total_hashes}") # 保存结果 self.save_results(hashes) return self.found_passwords def main(): cracker = HashCracker() # 破解哈希 try: results = cracker.crack_hashes('1.txt') # 显示部分结果 print("\n破解结果示例:") for i, (hash_val, password) in enumerate(list(results.items())[:10]): print(f"{hash_val}: {password}") except Exception as e: print(f"发生错误: {e}") if __name__ == "__main__": main()