大量のPDFファイルを暗号化レベル256ビットAESでパスワード保護する方法

こんにちは、その日暮らしです。
とある理由で大量のPDFファイルをパスワード保護する必要に迫られました。
私は、PDF-XChange-EditorというPDFファイルを編集するソフトを持っているのですが、これには複数のPDFファイルを一括で暗号化する機能は備わっていません。このソフトで暗号化を行うとしたらPDFファイルを一つ一つ手作業で暗号化するしかありません。
いろいろとググってみたところ、PyPDF2というPythonのパッケージを使って暗号化する方法を見つけることができました。しかし、この方法で暗号化したPDFファイルの暗号化レベルを調べてみると128ビットRC4とあり、さすがに古すぎます。冒頭のPDF-XChange-Editorで暗号化したときには「互換性」を「Acrobat X」にすることで暗号化レベルは256ビットAESとなり、十分です。そこで、PyPDF2パッケージを使って暗号化したときの暗号化レベルをAESにする方法をググってみたのですが、残念ながら具体的な方法を見つけることはできませんでした。
そのような状況のなかで、PyPDF2と同様にPDFファイルを操作することが可能なpikepdfというパッケージがあることが分かりました。早速試したところ、めでたく暗号化レベルを256ビットAESとすることができました。
当記事では、このときに作成したPythonのコードを紹介していきたいと思います。
準備
Pythonの実行環境の構築がまだの方は、以下の記事を参考にしてPythonの実行環境の構築を済ませてください。ただし、Pythonのインストールまでで結構です。これから紹介するコードを実行するだけならVisual Studio Codeのインストール以降の手順は必要ありません。
コード
以下のコードをコピペし適当なファイル名(拡張子は「.py」)で保存するか、ここからダウンロードしてください。
コードの説明はコード中のコメントを見ればわかると思うので省略しますが、実際に暗号化を行っているのは50行目と51行目になります。残りの部分は、元のDPFファイルのバックアップを行うコードです。
""" ☆☆☆ 指定されたフォルダ内の全PDFファイルを指定されたパスワードで暗号化するツール ☆☆☆ 1. pipコマンドをアップデートする。 C:\> python -m pip install --upgrade pip 2. パッケージpikepdfをインストールする。 C:\> pip install pikepdf 3. 実行する。 C:\> python encryptPDF.py -f Folder -p Password [-nb] -f Folder: 暗号化するPDFファイルが格納されているフォルダ -p Password: 暗号化に使用するパスワード -nb: 暗号化時に元のPDFファイルをバックアップしないことを指定するフラグ """ import sys import os import glob import shutil import itertools import argparse import pikepdf def encrypt_pdf(folder: str, password: str, noBackup: bool) -> None: """指定されたフォルダ内の全PDFファイルを指定されたパスワードで暗号化する。 Args: folder (str): 暗号化するPDFファイルが格納されているフォルダ password (str): 暗号化に使用するパスワード noBackup (bool): 暗号化時に元のPDFファイルをバックアップしないことを指定するフラグ """ # PDFファイルの一覧を取得する。 pdfs = [p.replace(os.sep, '/') for p in glob.glob(folder + '/*.pdf')] # それぞれのPDFファイルについて・・・。 for pdf in pdfs: print('**** ' + pdf) print('---> 暗号化を開始します。') # PDFファイルを開く。 with pikepdf.open(pdf) as org: # PDFファイルが既に暗号化されていたら処理をスキップする。 if org.is_encrypted: print('---> 既に暗号化されています。') continue # PDFファイルをバックアップ(リネーム)する。 bak = search_alternate_filepath(pdf.removesuffix('.pdf') + '.bak') shutil.move(pdf, bak) # バックアップ(リネーム)したPDFファイルを暗号化し元のPDFファイルのパスで保存する。 with pikepdf.open(bak) as org: org.save(pdf, encryption=pikepdf.Encryption(user=password)) # noBackupが指定されている場合バックアップ(リネーム)したPDFファイルを削除する。 if noBackup: os.remove(bak) print('---> 暗号化が終了しました。') def search_alternate_filepath(filepath: str) -> str: """バックアップ先などに使う代替のファイルパスを検索する。 Args: filepath (str): オリジナルのファイルパス Returns: str: 発見した代替のファイルパス """ # ファイルパスをベース名(フルパス)と拡張子に分割する。 base, ext = os.path.splitext(filepath) # iが1から始まる無限ループを回す。 for i in itertools.count(1): # 変数filepathが示すファイルが存在していたら・・・。 if os.path.exists(filepath): # 次の候補のファイルパスを作成する。 filepath = base + '({})'.format(i) + ext else: # ファイルが存在しないならここで終了。 return filepath if __name__ == '__main__': """コマンドライン引数を解析してメインルーチンを呼び出す。 """ # コマンドライン引数を解析する。 parser = argparse.ArgumentParser() parser.add_argument('-f', '--folder', type=str, required=True, metavar='Folder') parser.add_argument('-p', '--password', type=str, required=True, metavar='Password') parser.add_argument('-nb', '--nobackup', action='store_true') args = parser.parse_args() # 指定されたフォルダが存在しなければプログラムを終了する。 if not os.path.isdir(args.folder): print('The specified folder does not exist.') parser.print_usage() sys.exit(255) # メインルーチンを呼び出す。 encrypt_pdf(args.folder, args.password, args.nobackup)
使い方
とりあえず、お約束としてpipコマンドをバージョンアップしておきます。コマンドプロンプトを開き以下のコマンドを実行します。
python -m pip install --upgrade pip

次に、Pythonのpikepdfパッケージをインストールします。上と同様に以下のコマンドを実行します。
pip install pikepdf

いよいよPDFファイルの暗号化を行います。以下のようにコマンドを実行します。以下では、上で紹介したコードを「encryptPDF.py」という名前でフォルダ「C:\Hoge」に保存し、また、フォルダ「C:\Fuga」に置かれたすべてのPDFファイルをパスワード「Piyo」で暗号化する場合のコマンドを示しています。フォルダのパスや暗号化のパスワードはお使いの環境に合わせて適宜変更してください。
python C:\Hoge\encryptPDF.py -f C:\Fuga -p Piyo

このコマンドを実行すると元のファイルが拡張子を「.bak」に変更されてバックアップされ、暗号化されたPDFファイルが元のファイル名で保存されることがわかると思います。

以上、「大量のPDFファイルを暗号化レベル256ビットAESでパスワード保護する方法」でした。
この記事を書いた人
ディスカッション
コメント一覧
まだ、コメントがありません