PDFファイルの暗号化について調べてみた

コマンドラインでPDFファイルをパスワード保護・暗号化したり、復号したり、ファイルのメタデータから暗号化の詳細を確認する方法を紹介します。
2023.05.15

下記ブログの検証のために、PDFファイルの暗号化や復号を試しました。今回は調べた内容をブログにします。

暗号化されたPDFをCloudinaryにアップロードするには

検証環境は MacBook で、このブログでは以下のような内容を取り扱います。

Previewで簡単にやってみる

暗号化

Macでは、ツールをインストールせずとも Preview のデフォルト機能でファイルを暗号化できます。

詳しい暗号化の手順はこちらのブログにあるので、ここでは設定項目について確認します。

こちら、上部で囲ってある部分がファイルを開くためのパスワード設定で、下部が権限を設定するための所有者パスワードの設定です。

権限には以下のものが含まれます。

  • 印刷
  • テキストや図のコピー
  • ページの追加、削除、回転
  • 注釈や署名の追加
  • 既存のフォームフィールドへの入力

これらのチェックをはずすことで、対象のアクションを行うのに所有者パスワードが必要となります。

なお、一度暗号化したファイルを復号することはデフォルト機能でできないようです。Previewではファイルを開く際のパスワード保護は解除できますが、一度設定した所有者パスワードをなくすことはできません。検証に使う場合は、ファイルをコピーしてから試すことをおすすめします。

暗号化の確認

次に、暗号化の状況を確認しましょう。こちらも Preview で簡単な情報は得られます。

ファイルを開いた状態で、Tools > Show Inspector を選択、もしくは Command+I を押します。下図の右のような小窓が現れ、暗号化の設定状況を確認できます。(これは、ユーザ・所有者パスワードを両方指定し、チェックはすべて外して設定したファイルを開いた状態)

この Preview を使った方法の場合、128-bit (Standard V4.4)で暗号化されています。そう、暗号化は他にも種類があるのです。

暗号化の種類

PDFファイルの暗号化には、2つのアルゴリズムがあります。

  • RC4:暗号と復号に同じアルゴリズムを使い、十分にセキュアではないため、PDF 2.0 で廃止された
  • AES (Advanced Encryption Standard):現在様々な場所で広く使われている標準的な方式

指定するパスワードや権限設定などのパラメータを用いてバイナリの暗号鍵が算出されますが、その鍵の長さが40、128、256ビットと大きくなるほど最新/安全です。

※ビット長は設定するパスワードの長さには関係ありません。

また、PDFにはバージョンがあり、Adobe社がリリースして以来アップデートを重ねています。現時点の最新は2.0です。

そして、対応している暗号化のアルゴリズムとビット長はバージョンによって異なります。詳しい対応表は下記ページに載っていました。

暗号化について理解が深まったところで、具体的に特定の暗号化と復号を行ってみます。

コマンドラインで暗号化とその確認

今回はコマンドラインでQPDFとExiftoolというツールを使います。各ツールの詳しい説明は後で書きます。

やってみた

暗号化されていない file.pdf から、各ビット長に暗号化したファイルを生成します。

# 128-bit暗号化 / ファイルを開くパスワード保護なし / ファイル変更を制限(要所有者パスワード)
% qpdf --encrypt "" ownerpw 128 --modify=none -- \
  --allow-weak-crypto \ 
  file.pdf file_qpdf128.pdf
# 256-bit暗号化 / ファイルを開くパスワード保護あり / ファイル変更と抽出を制限、印刷は許可
% qpdf --encrypt userpw ownerpw 256 \
  --modify=none --extract=n --print=full -- \
  file.pdf file_qpdf256.pdf

128-bitで暗号化したファイルを確認します。

こちらはパスワード保護しなかったので、普通にファイルが開きました。ですが、オプションで変更を制限したため、Previewの機能でファイルに図形を挿入しようとしたら、以下のように所有者パスワードの入力が求められました。

ここに“ownerpw”を入力すると、図形が入れられるようになり、右窓の権限で×と示されているものもすべて緑のチェックに変わりました。

今度は、256-bitで暗号化したファイルを確認します。

こちらはパスワード保護したので、パスワード入力が求められ、このままでは何の権限もありません。

”userpw”を入力すると、ファイルが開きました。

印刷には進むことができますが、こちらも図形の挿入のような編集には所有者パスワードが求められ、またテキストを選択してコピーしようとしても以下の通り同様です。

いずれもオプションで設定した通りの動きでしたね。

復号も試しておきます。

% qpdf --decrypt --password=ownerpw file_qpdf256.pdf file_decrypt.pdf

生成されたファイルは、パスワードなしで開き、図形挿入やテキストコピーもできました。

それでは、メタデータから暗号化を確認します。

% exiftool -TAG -Encryption -UserAccess -Warning *.pdf                            
======== file.pdf
======== file_decrypt.pdf
======== file_qpdf128.pdf
Encryption                      : Standard V2.3 (128-bit)
User Access                     : Print, Copy, Extract, Print high-res
======== file_qpdf256.pdf
Encryption                      : Standard V5.6 (256-bit)
User Access                     : Print, Extract, Print high-res
Warning                         : [minor] Decryption is very slow for encryption V5.6 or higher
    4 image files read

暗号化されていない元ファイルと復号ファイルには結果がなく、暗号化されたファイルは各ビット長と指定した権限が示されることが確認できました。


解説:QPDF

コマンドラインツール qpdf を使うことで、指定したビット長の暗号化が行えます。

# QPDF のインストール
% brew install qpdf

# ファイルの暗号化
% qpdf --encrypt {ユーザパスワード} {所有者パスワード} {ビット長:40/128/256} \
  {(任意)権限設定のオプション} -- \
  {(任意)--allow-weak-crypto} \
  {元ファイル.pdf} {新しいファイル名.pdf}

# ファイルの復号化
% qpdf --decrypt --password={所有者パスワード} {元ファイル.pdf} {新しいファイル名.pdf}

暗号化のオプションについて:

  • ユーザパスワード:ファイルを開く際に使うもの。パスワード保護しない場合は、空(””)を指定。
  • 権限設定:以下を許可または制限する。詳しくはドキュメントを。
    • --print (印刷)
    • —modify (ドキュメントの変更)
    • —extract (テキストや図のコピー)
    • —annotate (注釈)
  • --allow-weak-crypto:40/128を指定する場合に必要。現在256ビット未満のビット長は推奨されていないため、オプションで明示的に合意を示す。

解説:Exiftool

コマンドラインツール Exiftool を使うことで、ファイルのメタデータから暗号化の詳細を確認できます。

OSごとの詳しいインストール方法は公式ページで丁寧に記述されています。

# exitfool のインストール
# 公式のトップページ(https://exiftool.org)でリンクをクリックしてダウンロード後、以下を実行
% cd $HOME/Downloads

% tar -xzf Image-ExifTool-12.62.tar.gz

% cd Image-ExifTool-12.62 

% sudo cp -r exiftool lib /usr/local/bin

メタデータの確認には、基本的にはファイル名を指定するだけです。オプションでパスワードやタグを指定できます。

# ファイルのメタデータ確認
% exiftool {(任意)タグ指定で結果出力} {(任意)ユーザパスワード} {ファイル名.pdf}

# 以下、タグ指定せず、パスワード保護を解除した場合の出力例
% exiftool -password userpw file_qpdf256.pdf
ExifTool Version Number         : 12.62
File Name                       : file_qpdf256.pdf
Directory                       : .
File Size                       : 227 kB
File Modification Date/Time     : 2023:05:12 22:41:23+02:00
File Access Date/Time           : 2023:05:12 22:54:00+02:00
File Inode Change Date/Time     : 2023:05:12 22:54:00+02:00
File Permissions                : -rw-r--r--
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
PDF Version                     : 1.7
Linearized                      : No
Encryption                      : Standard V5.6 (256-bit)
Warning                         : [minor] Decryption is very slow for encryption V5.6 or higher
User Access                     : Print, Extract, Print high-res
Author                          : Pyshnyuk
Create Date                     : 2023:05:12 20:22:11Z
Creator                         : Microsoft® PowerPoint® 2016
Modify Date                     : 2023:05:12 20:22:11Z
Producer                        : macOS Version 13.3.1 (a) (Build 22E772610a) Quartz PDFContext
Title                           : PowerPoint-Präsentation
Tagged PDF                      : Yes
Page Count                      : 1
Profile CMM Type                : Apple Computer Inc.
(中略)
Media White Point               : 0.95045 1 1.08905
Gray Tone Reproduction Curve    : (Binary data 2060 bytes, use -b option to extract)

オプションについて:

  • タグ指定
    • -TAG {-タグ名} で指定すると、特定タグののみ表示
    • -T {-タグ名} で指定すると、特定タグののみ表示
    • 暗号化に関連するタグは -Encryption-UserAccess-Warning
  • ユーザパスワード -password {ユーザパスワード}
    • ファイルを開く際のパスワード保護がされている場合は、一部データが制限される(上の例ではAuthor以降は表示されない)
    • パスワードを指定すると、全データにアクセスできる

暗号化タグ Warning について:

  • 256-bit 暗号化の場合は、パスワード保護にかかわらず常に「[minor] Decryption is very slow for encryption V5.6 or higher」のようです。
  • それ以外の暗号化の場合は、パスワード保護されているときのみ「Document is password protected (use Password option)」と表示され、保護がなければ値は空のようです。

備考:2ファイルのメタデータ全体を比較

出力結果はファイルによりますがかなり長いので、メタデータ全体を比較する場合は一度ファイル出力してdiffすると扱いやすかったです。

% exiftool file_qpdf128.pdf > 128.txt

% exiftool file_qpdf256.pdf > 256.txt

% diff -y --suppress-common-lines 128.txt 256.txt
File Name                       : file_qpdf128.pdf		|       File Name                       : file_qpdf256.pdf
File Size                       : 224 kB			|       File Size                       : 227 kB
File Modification Date/Time     : 2023:05:12 22:39:14+02:       |       File Modification Date/Time     : 2023:05:12 22:41:23+02:
File Access Date/Time           : 2023:05:12 22:53:56+02:       |       File Access Date/Time           : 2023:05:12 22:54:00+02:
File Inode Change Date/Time     : 2023:05:12 22:53:56+02:       |       File Inode Change Date/Time     : 2023:05:12 22:54:00+02:
PDF Version                     : 1.4				|       PDF Version                     : 1.7
Encryption                      : Standard V2.3 (128-bit)       |       Encryption                      : Standard V5.6 (256-bit)
User Access                     : Print, Copy, Extract, P       |       Warning                         : [minor] Decryption is v
Author                          : Pyshnyuk			|       User Access                     : Print, Extract, Print h
Create Date                     : 2023:05:12 20:22:11Z		<       
Creator                         : Microsoft® PowerPoint?       <       
Modify Date                     : 2023:05:12 20:22:11Z		<       
Producer                        : macOS Version 13.3.1 (a       <       
Title                           : PowerPoint-Präsentatio       <       
Tagged PDF                      : Yes				<       
Page Count                      : 1				<
(後略)

参考サイト