電子帳單每份都要輸身分證?實測 pikepdf:60 份 PDF 0.53 秒解開,但一個壞檔就讓程式停擺
重點摘要
- 用 pikepdf 寫十幾行 Python,輪流試自己的身分證與生日密碼,60 份 AES-256 加密的假帳單 PDF 在 0.53 秒內全部解開,600 份約 5.08 秒。
- pikepdf 對 RC4-40、RC4-128、AES-128、AES-256 四種 PDF 加密方式,只要密碼正確都能解開;密碼大小寫不同(小寫 a123456789)就打不開。
- 資料夾混進一個損壞的 PDF 時,最簡單的批次腳本會因 PdfError 直接中斷,實測 60 份只解了 36 份,需要另外處理壞檔。
- pikepdf 沒有破解功能,只能用已知密碼打開自己的檔案;它是 Python 套件,需要會執行程式。
- 結論: 會寫一點 Python 的人,用 pikepdf 批次解開自己的加密電子帳單又快又可靠,但要自己處理壞檔,否則只會做一半。
- 適合: 每月收大量加密電子帳單、想批次歸檔或合併,且能執行簡單 Python 腳本的人。
- 不適合: 完全不想碰指令的人,以及想打開不知道密碼之檔案的人(它沒有破解功能)。
| 實測項目 | 結果 |
|---|---|
| 安裝(pip install pikepdf) | 約 3 秒 |
| 60 份 AES-256 假帳單批次解密 | 0.51–0.53 秒,60/60 成功 |
| 600 份批次解密 | 5.08 秒,600/600 成功 |
| RC4-40/RC4-128/AES-128/AES-256 | 密碼正確時全部解開 |
| 密碼小寫、少一碼、多一個空白 | 都打不開 |
| 混進 1 個損壞 PDF | 腳本中斷,只解 36/60 份 |
| 解開後 60 份合併 | 60 頁、103KB,不到 0.1 秒 |
| 解開後內容 | 與加密前原檔逐位元組相同 |
月底想對帳,打開信箱:信用卡、電信、保險的電子帳單,每一份 PDF 都要輸入身分證字號才打得開。想翻一整年的紀錄,三張卡加電信加保險,就是 60 份、60 次輸入。
pikepdf 是 GitHub 上一個不到三千星(實測時 2,808 星)的 Python 套件,專門讀寫、修復、轉換 PDF,底層是老牌的 C++ 函式庫 qpdf。它沒有圖形介面,但只要十幾行程式,就能用「你自己知道的密碼」把整個資料夾的帳單一次解開。這篇記錄實際跑出來的結果,包括兩個會讓人卡住的地方。
測試設備: Mac mini M4 Pro(12 核、64GB),Python 3.12,pikepdf 10.16.0(內含 qpdf 12.4.2)。
全部使用假資料: 帳單是我自己用程式產生的,範例身分證字號 A123456789、範例生日 19900101,沒有用任何真實帳單或個資。
安裝:一行,約 3 秒
pip install pikepdf
有預編譯好的版本,不用另外裝系統套件,實測約 3 秒裝好。
準備 60 份加密的假帳單
我做了一年份的假帳單:三張信用卡各 12 份、電信 12 份、保險 12 份,共 60 份。信用卡與電信用身分證當密碼,保險用生日當密碼,加密方式是 AES-256。不給密碼直接開,pikepdf 會丟出 PasswordError: invalid password。
核心腳本:輪流試自己的密碼
import pikepdf, glob, os, time
mine = ['A123456789', '19900101'] # 自己的密碼
os.makedirs('unlocked', exist_ok=True)
t, ok = time.time(), 0
for f in sorted(glob.glob('bills/*.pdf')):
for pw in mine:
try:
with pikepdf.open(f, password=pw) as p:
p.save(f.replace('bills', 'unlocked'))
ok += 1; break
except pikepdf.PasswordError:
pass
print(f'解開 {ok} 份,{time.time()-t:.2f} 秒')
邏輯很單純:每份帳單把你的密碼清單從頭試一遍,打得開就另存一份到 unlocked 資料夾。原始檔不會被改動。

python3 unlock.py
# 解開 60 份,0.53 秒
我另外比對過:解開後的檔案不再需要密碼,頁面內容和加密前的原檔逐位元組相同。
實測數字
| 項目 | 結果 |
|---|---|
| 安裝(pip) | 約 3 秒 |
| 60 份 AES-256 帳單解開 | 0.51–0.53 秒,60/60 成功 |
| 放大到 600 份 | 5.08 秒,600/600 成功 |
| 加密方式 | RC4-40、RC4-128、AES-128、AES-256 四種都解得開 |
| 密碼打成小寫 a123456789 | 打不開 |
| 密碼少一碼、多一個空白 | 都打不開 |
| 混進 1 個壞檔 | 程式中斷,60 份只解了 36 份 |
| 60 份合併成一份 | 60 頁、103KB,不到 0.1 秒 |
踩雷一:大小寫要完全一樣
台灣的帳單密碼常是身分證字號,開頭是英文字母。我分別試了 a123456789 和 A123456789:小寫直接回報密碼錯誤,大寫才打得開。多打一個空白也一樣打不開。寫密碼清單時要照帳單通知上寫的格式,一個字都不能差。
踩雷二:一個壞檔,整批停下來
這是實測裡最痛的一點。我在資料夾裡放了一個「下載失敗」的假 PDF(其實是一段 HTML),再跑一次同樣的腳本:

python3 unlock.py 2>&1 | tail -1
# pikepdf._core.PdfError: bills/broken.pdf: unable to find trailer dictionary while recovering damaged file
程式照檔名順序處理,碰到壞檔就整個中斷:60 份只解了排在它前面的 36 份,後面 24 份完全沒處理,而且沒有任何「完成幾份」的訊息。從信箱批次下載帳單時,偶爾有一份沒下載完整很常見,所以實際使用建議在 except pikepdf.PasswordError 後面再接住 pikepdf.PdfError,印出壞檔名稱後跳過(這個改法我沒有在本次實測中重跑,請自行確認)。
解開之後:合併成一份全年帳單
import pikepdf, glob
year = pikepdf.new()
for f in sorted(glob.glob('unlocked/*.pdf')):
year.pages.extend(pikepdf.open(f).pages)
year.save('2026全年帳單.pdf')
60 份合併成一份 60 頁、103KB 的 PDF,不到 0.1 秒。要找某個月的扣款,開一個檔就能翻完。
怎麼判讀結果
- 印出「解開 N 份」時,N 應該等於資料夾裡的檔案數;少了就代表有檔案每組密碼都試過仍打不開,或程式中途停了。
- 出現
PasswordError是密碼不對;出現PdfError通常是檔案本身壞了,不是密碼問題。 - 另一個觀察:只「限制列印」、沒有設開啟密碼的 PDF,pikepdf 不用密碼就能開,並會回報該檔不允許列印。這類權限設定和開啟密碼是兩回事。
我的結論
我會留著它。一年整理一次帳單、或要把一疊加密 PDF 交給會計,十幾行程式就省下幾十次輸入,速度也完全不是問題。但它是 Python 套件,不是點兩下就能用的 App:至少要會執行一個 .py 檔,壞檔也要自己處理,否則它會安靜地只做一半。
它沒有破解功能,只能用你已經知道的密碼打開你自己的檔案;忘記密碼的檔案,它一樣打不開。
適合: 每個月收一堆加密電子帳單、想批次整理或歸檔的人;會一點 Python,或願意照著範例改密碼清單的人。
不適合: 完全不想碰指令的人;想打開不知道密碼的檔案的人(它做不到,也不該這樣用)。
專案資訊
- 專案:pikepdf/pikepdf
- 文件:https://pikepdf.readthedocs.io/
- 授權:MPL-2.0
- 受測版本:pikepdf 10.16.0(qpdf 12.4.2)