C# で PDF が暗号化されているかを検出し、正しいパスワードを検証する

## はじめに：なぜ PDF の暗号化状態を検出する必要があるのか？
暗号化された PDF は、OCR 文字認識やコンテンツ抽出、形式変換などのバッチ文書処理システムで直接操作することができません。PDF ファイルの暗号化状態を検出することで、パスワード認証の失敗によるプロセスの中断を回避することができます。
本文では、[**Free Spire.PDF for .NET**](https://www.e-iceblue.com/Introduce/free-pdf-component.html)（無料の.NET PDF 処理ライブラリ）を使用して、C# を用いて PDF が暗号化されているかどうかを検出し、正しいパスワードを検証する方法を紹介します。

## Free Spire.PDF for .NET の概要
**主な機能：**
* 基本的な PDF の作成、編集、暗号化検出機能を無料で提供
* .NET Framework と .NET Core をサポート
* Adobe に依存しない

**インストール方法：**
この無料の .NET PDF ライブラリは、NuGet パッケージ マネージャーを通じてインストールできます。
1. Visual Studio を開き、プロジェクト内の「NuGet パッケージの管理」を右クリックします。
1. 「Free Spire.PDF」を検索します。
1. 適切なバージョンを選択してインストールします。


> ⚠️ **重要な注意点：暗号化検出 ≠ パスワード解読ツールです。Spire.PDF は合法的に所有しているファイルの操作のみを行います。**

## C# で PDF ドキュメントが暗号化されているかを検出する
PDF ファイルの暗号化状態を検出するには、**`PdfDocument`** クラスの **`IsPasswordProtected(string fileName)`** メソッドを直接使用できます。このプロパティはブール値を返し、「true 」の場合は PDF が暗号化されていることを、「false」 の場合は暗号化されていないことを示します。

C# の例代码は以下の通りです：
```csharp
using Spire.Pdf;
namespace CheckIfPdfIsProtected
{
    class Program
    {
        static void Main(string[] args)
        {
            // PDF ドキュメントのパスを指定します
            string pdfPath = "EncryptedPDF.pdf";

            // PDF ドキュメントが暗号化されているかを検出します
            bool isProtected = PdfDocument.IsPasswordProtected(pdfPath);

            // 結果を出力します
            if (isProtected)
            {
                Console.WriteLine("このPDFは暗号化されています。");
            }
            else
            {
                Console.WriteLine("このPDFは暗号化されていません。");
            }
        }
    }
}
```
出力結果：
![CheckEncryptPDF.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/35e4d356-e53f-49a8-8be0-b13be6317bdf.png)


## C# で PDF の正しいパスワードをテストする
PDF が暗号化されていることが検出された場合、次に正しいパスワードをテストする必要があります。Free Spire.PDF for .NET には直接パスワードを検証するインターフェースはありませんが、パスワードで PDF ファイルを開こうとして例外をキャッチすることで検証できます。
例の C# コードは以下の通りです：
```csharp
using Spire.Pdf;
namespace DetermineTheCorrectPasswordOfPdf
{
    class Program
    {
        static void Main(string[] args)
        {
            // PDF ファイルとテストするパスワードを指定します
            string pdfPath = " EncryptedPDF.pdf";
            string[] testPasswords = { "admin@2023", "abc", "12345" };

            // テストするパスワードを順に処理します
            foreach (var pwd in testPasswords)
            {
                if (ValidatePdfPassword(pdfPath, pwd))
                {
                    Console.WriteLine($"成功！正しいパスワードは：{pwd}");
                    break;
                }
            }

            // PDF のパスワードを検証するメソッド
            static bool ValidatePdfPassword(string filePath, string password)
            {
                // テストするパスワードで順にPDFを開いて検証します
                PdfDocument pdf = new PdfDocument();
                try
                {
                    pdf.LoadFromFile(filePath, password);
                    // 例外が発生しない = パスワードが正しい
                    return true;
                }
                catch (Exception)
                {
                    return false; // パスワードが間違っています
                }
                finally
                {
                    pdf.Close();
                }
            }
        }
    }
}
```

出力結果：
![CheckPassword.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/6ea447de-e567-4683-bd93-114d43f007bd.png)


## バルク検出 + パスワードテスト（完全な企業向けソリューション）
バッチ文書処理が必要なシーン（以下の例を含む）において：
* **企業文書管理**：暗号化 PDF を一括検出し、部署のデフォルトパスワードなどの一般的なパスワードを試行することで、パスワード忘れに起因する文書アクセス問題を解消します。
* **データ復旧**：復旧された過去の暗号化文書に対し、会社の古いパスワードなどの事前設定されたパスワードライブラリを用いて復号を試み、データの利用可能性を高めます。
* **セキュリティ監査**：PDF のパスワード強度を一括検査し、簡易パスワードで解読可能なファイルを検出した際に弱パスワードのリスクを警告し、パスワードの強化を推進します。

例の C# コードは以下の通りです：
```csharp
using Spire.Pdf;
using System.IO;

public class PdfSecurityChecker
{
    public static void Main()
    {
        // 指定されたフォルダ内のすべての PDF ドキュメントをスキャンします
        string folderPath = @"F:\PDFs\";
        foreach (string file in Directory.GetFiles(folderPath, "*.pdf"))
        {
            // PDF ドキュメントが暗号化されているかを検証します
            bool isProtected = PdfDocument.IsPasswordProtected(file);
            Console.WriteLine($"{Path.GetFileName(file)} が暗号化されているか: {isProtected}");

            // もしPDFが暗号化されている場合、その正しいパスワードを順に検証する
            if (isProtected)
            {
                TestPasswords(file, new[] { "default", "company_secret", "temp_pwd", "user123", "abc" });
            }
        }
    }

    // 正しいパスワードを検証する
    private static void TestPasswords(string filePath, string[] passwords)
    {
        foreach (string pwd in passwords)
        {
            if (ValidatePdfPassword(filePath, pwd))
            {
                Console.WriteLine($"  検証成功！パスワード: {pwd}");
                return;
            }
        }
        Console.WriteLine("  すべてのパスワードのテストに失敗しました！");
    }

    static bool ValidatePdfPassword(string filePath, string password)
    {
        // テストするパスワードで順にPDFを開いて検証します
        PdfDocument pdf = new PdfDocument();
        try
        {
            pdf.LoadFromFile(filePath, password);
            // 例外が発生しない = パスワードが正しい
            return true;
        }
        catch (Exception)
        {
            return false; // パスワードが間違っています
        }
        finally
        {
            pdf.Close();
        }
    }
}
```

## まとめ
本文では、Free Spire.PDF ライブラリを使用して C# で PDF の暗号化状態を検出し、パスワードをテストする実用的な技術について詳細に紹介しました。主なポイントは以下の通りです：
✅ **`IsPasswordProtected`** メソッドを使用して暗号化状態を検出する
✅ **`LoadFromFile`** メソッドを使用してパスワードで順に PDF ドキュメントを読み込んでパスワードの有効性をテストする
✅ 複数の PDF ドキュメントのバルク処理を実装する

これらの例が日常的な業務で暗号化された PDF ドキュメントを効率的かつ安全に処理するのに役立てば幸いです。

* * *
さらに詳しいPDFセキュリティ機能をご覧になりたい方は：

https://www.e-iceblue.com/Tutorials/Spire.PDF/Spire.PDF-Program-Guide/Spire.PDF-Program-Guide-Content.html