题目:
假定有一个加密的PDF文档,你忘记了口令,但记得它是一个英语单词。尝试猜测遗 忘的口令是很无聊的任务。作为替代,你可以写一个程序,尝试用所有可能的英语单词来 解密这个PDF文档,直到找到有效的口令。这称为蛮力口令攻击。从异步社区本书对应页 面下载文本文件dictionary.txt。这个字典文件包含44 000多个英语单词,每个单词占一 行。
利用第9章学过的文件读取技巧来读取这个文件,并创建一个单词字符串的列表。然 后循环遍历这个列表中的每个单词,将它传递给decrypt()函数,如果这个函数返回整 数0,口令就是错的,程序应该继续尝试下一个口令。如果decrypt()函数返回1,程序 就应该终止循环,并输出破解的口令。你应该尝试每个单词的大小写形式(在我的笔记本 电脑上,遍历来自字典文件的88 000个大小写单词只要几分钟时间。这就是不应该使用简 单英语单词作为口令的原因)。
代码如下:
from PyPDF2 import PdfReader
def decrypt_pdf(password):
# 为避免解密失败而报错,使用try-except语句
try:
with open('encrypt_file.pdf', 'rb') as file: # 用读二进制模式打开需要解密的PDF文件
pdfReader = PdfReader(file)
# 检查PDF文件是否加密
if pdfReader.is_encrypted:
pdfReader.decrypt(password)
# 检查是否可以获取PDF文件第1页的文本字符串
if pdfReader.pages[0].extract_text():
# 若能获取第1页的文本,则表示解密成功,返回1
return 1
except:
# 若是解密失败,则跳过
pass
def brute_force_attack(dictionary):
with open(dictionary, 'r') as file: # 用读模式打开含有所有口令的文件
# 将每一个口令都存储在变量中
words = file.read().splitlines()
# 遍历每一个口令并开始破解
for word in words:
# 先尝试小写的口令
if decrypt_pdf(word.lower()):
print('Password is decrypted: ', word.lower())
# 口令正确,则打印出来,并退出程序
break
# 再尝试全大写的口令
elif decrypt_pdf(word.upper()):
print('Password is decrypted: ', word.upper())
break
# 调用破解口令的函数
brute_force_attack('dictionary.txt') # dictionary.txt应替换为该文件的实际路径