首頁 > 軟體

實用指令碼!利用Python對PDF進行加密、解密操作

2021-05-17 14:30:06

來源:早起Python

作者:陳熹

大家好,我是早起。

本文將分享如何利用 Python 對 PDF 進行加密和解密操作,主要利用到之前多次介紹過的PyPDF2模組。

PDF 加密

在之前的文章PDF合併、拆分、水印、加密中簡單提到過加密一個 PDF 檔案的方法,我們先拿自己隨意的一個PDF 檔案試一下:

from PyPDF2 import PdfFileWriter, PdfFileReaderpath = r'C:xxx' # 這裡填寫目標 PDF 所在的路徑pdf_reader = PdfFileReader(path + r'test.pdf')pdf_writer = PdfFileWriter()for page in range(pdf_reader.getNumPages()):pdf_writer.addPage(pdf_reader.getPage(page))pdf_writer.encrypt('a123') # 設定密碼為 a123with open(path + r'test.pdf', 'wb') as out: pdf_writer.write(out)

上面程式碼的運行邏輯是:例項化一個 PDF 寫入器和讀取器,讀取器讀取完目標 PDF 檔案後,一頁一頁交給寫入器,然後對寫入器設定密碼並輸出。看一下運行結果:

可見這個 PDF 檔案成功設定上了密碼,如果有多個PDF需要加密,可以寫一個簡單的迴圈利用上述指令碼批量處理,此處不再展開說明。

PDF 已知密碼解密

如果知道密碼的情況下,想直接取消 PDF 的加密,可以用.decrypt,解密的過程需要讀取器和寫入器共同配合。但區別於加密.encrypt,.decrypt 是針對讀取器進行解密的,而不是寫入器

from PyPDF2 import PdfFileWriter, PdfFileReader

path = r'C:xxx'pdf_reader = PdfFileReader(path + r'test.pdf')pdf_reader.decrypt('a123') #pdf_writer = PdfFileWriter()for page in range(pdf_reader.getNumPages()):pdf_writer.addPage(pdf_reader.getPage(page))with open(path + r'test.pdf', 'wb') as out: pdf_writer.write(out)

上面程式碼的運行邏輯是:首先用讀取器讀取加密檔案,然後直接在讀取器上使用.decrypt進行解密,逐頁傳到剛例項化的寫入器後統一輸出,就完成了解密

PDF 暴力解密

暴力破解,其實就是通過手上已經有的密碼庫,或者完全通過數字、字母、符號的窮舉,將可能的密碼都放進去,逐個嘗試直到成功。

「目前暴力破解只適用於已知密碼位數少,由簡單的數字、字母構成」

假設今天要破解的密碼就是a123,已知密碼 4 位且由數字和小寫字母組成。破解又分為兩種情況:

1. 手上有密碼本

第一種情況,知道大概密碼,可以整理成一個

password.txt,保證可能的密碼一定在其中:

首先讀取.txt檔案獲取其中所有密碼(示例檔案只有 9 個密碼):

passw = []path = r'C:Scientific ResearchPython'file = open(path + r'password.txt')for line in file.readlines():passw.append(line.strip())print(passw)file.close()

然後就可以用密碼本的密碼做暴力破解:

from PyPDF2 import PdfFileReader

passw = []path = r'C:xxx'file = open(path + r'password.txt')for line in file.readlines():passw.append(line.strip())file.close()path = r'C:xxx'pdf_reader = PdfFileReader(path + r'test).pdf')for i in passw: if pdf_reader.decrypt(i): print(f'破解成功,密碼為{i}') else: print(f'破解不成功,密碼{i}錯誤')

2. 手術無密碼本,完全窮舉

首先介紹

itertools,可以構建含需要組合的生成器供後續迭代:

import itertoolsmylist = ("".join(x) for x in itertools.product("0123456789abcdef", repeat=4))print(next(mylist))

利用這個方法就可以用while迴圈嘗試暴力破解(為了減少時間,生成器用"abc123"生成組合):

import itertools

from PyPDF2 import PdfFileReadermylist = ("".join(x) for x in itertools.product("123abc", repeat=4))path = r'C:xxx'pdf_reader = PdfFileReader(path + r'test.pdf')while True:i = next(mylist) if pdf_reader.decrypt(i): print(f'破解成功,密碼為{i}') break else: print(f'破解不成功,密碼{i}錯誤')

可以看到最後也成功破解了,但需要注意:但即使是這麼簡單的組合也耗費了一點時間,如果複雜的密碼破解難度和破解時間就指數級增長了,暴力的窮舉法就不一定適用,可以根據需求具體調整規則,縮小範圍再進行嘗試。


IT145.com E-mail:sddin#qq.com