PDF のデジタル署名は、文書の改ざん検知と署名者の識別を目的として広く利用されています。契約書や申請書類など、内容の真正性が求められる場面では、署名の付与と検証が運用の前提となることがあります。一方、署名済みの PDF に対してレイアウト調整や内容の修正が必要になった場合、署名を一時的に削除して編集可能な状態に戻す必要が生じることもあります。
本記事では、.NET 向けの PDF ライブラリである Spire.PDF for .NET を使用し、C# で PDF にデジタル署名を追加する方法と、既存の署名を削除する方法を解説します。
前提条件とライブラリの導入
本記事では、PDF のフォームフィールド操作と署名処理を行えるライブラリとして Spire.PDF for .NET を使用します。NuGet パッケージマネージャーコンソールで以下のコマンドを実行して導入します。
PM> Install-Package Spire.PDF
デジタル署名の追加:基本の流れ
署名の追加は、PDF の読み込み、証明書の読み込み、署名オブジェクトの作成、保存という流れで行います。署名には「不可視署名」と「可視署名」の 2 種類があり、用途に応じて使い分けます。
不可視署名を追加する
不可視署名は、ページ上に署名の外観を表示せず、文書の改ざん検知のみを目的とする場合に使用します。PdfSignature オブジェクトを作成し、証明書を渡したうえで、文書の権限を設定して保存します。
using Spire.Pdf;
using Spire.Pdf.Security;
namespace AddInvisibleSignature
{
class Program
{
static void Main(string[] args)
{
// PdfDocument オブジェクトを作成
PdfDocument doc = new PdfDocument();
// 署名対象の PDF を読み込む
doc.LoadFromFile("sample.pdf");
// 証明書を読み込む
PdfCertificate cert = new PdfCertificate("MyCertificate.pfx", "password");
// PdfSignature オブジェクトを作成(最終ページを指定)
PdfSignature signature = new PdfSignature(
doc, doc.Pages[doc.Pages.Count - 1], cert, "MySignature");
// 変更を禁止し、フォーム入力のみ許可
signature.DocumentPermissions = PdfCertificationFlags.ForbidChanges
| PdfCertificationFlags.AllowFormFill;
// 別ファイルとして保存
doc.SaveToFile("InvisibleSignature.pdf");
doc.Close();
}
}
}
署名の対象ページには、文書の最終ページを指定しています。署名ページを特定のページに固定したい場合は、doc.Pages[0] のようにインデックスを直接指定することもできます。
可視署名を追加する
可視署名では、ページ上の任意の位置に署名の詳細情報や手書き画像を表示できます。Bounds プロパティで位置とサイズを指定し、GraphicsMode で表示内容を制御します。
using System;
using System.Drawing;
using Spire.Pdf;
using Spire.Pdf.Security;
using Spire.Pdf.Graphics;
namespace AddVisibleSignature
{
class Program
{
static void Main(string[] args)
{
PdfDocument doc = new PdfDocument();
doc.LoadFromFile("sample.pdf");
PdfCertificate cert = new PdfCertificate("MyCertificate.pfx", "password");
// 署名オブジェクトを作成し、位置とサイズを指定
PdfSignature signature = new PdfSignature(
doc, doc.Pages[doc.Pages.Count - 1], cert, "MySignature");
RectangleF rectangleF = new RectangleF(
doc.Pages[0].ActualSize.Width - 260 - 54, 200, 260, 110);
signature.Bounds = rectangleF;
signature.Certificated = true;
// 表示モード:画像と署名の詳細情報を表示
signature.GraphicsMode = GraphicMode.SignImageAndSignDetail;
// 署名に含める情報を設定
signature.NameLabel = "Signer:";
signature.Name = "署名者名";
signature.ContactInfoLabel = "Phone:";
signature.ContactInfo = "0123456";
signature.DateLabel = "Date:";
signature.Date = DateTime.Now;
signature.LocationInfoLabel = "Location:";
signature.LocationInfo = "Tokyo";
signature.ReasonLabel = "Reason:";
signature.Reason = "文書の承認";
signature.DistinguishedNameLabel = "DN:";
signature.DistinguishedName = signature.Certificate.IssuerName.Name;
// 署名画像の読み込み
signature.SignImageSource = PdfImage.FromFile("handwrittingSignature.png");
// 署名の詳細情報に使用するフォント
signature.SignDetailsFont = new PdfTrueTypeFont(
new Font("Arial Unicode MS", 12f, FontStyle.Regular));
// 変更を禁止し、フォーム入力のみ許可
signature.DocumentPermissions = PdfCertificationFlags.ForbidChanges
| PdfCertificationFlags.AllowFormFill;
doc.SaveToFile("VisibleSignature.pdf");
doc.Close();
}
}
}
GraphicsMode には SignDetail(詳細情報のみ)、SignImageOnly(画像のみ)、SignImageAndSignDetail(両方)が指定できます。画像を表示する場合は SignImageSource に PdfImage オブジェクトを設定します。また、Certificated を true にすると、署名が「認定署名」として扱われます。
デジタル署名の削除
署名済み PDF からデジタル署名を削除するには、PDF のフォームフィールドを走査し、署名フィールド(PdfSignatureFieldWidget)を特定して削除します。署名は PDF のフォームコントロールとして埋め込まれているため、フォームフィールドのコレクションから除去することで署名が解除されます。
using Spire.Pdf;
using Spire.Pdf.Widget;
namespace RemoveSignature
{
class Program
{
static void Main(string[] args)
{
// 署名済みの PDF を読み込む
PdfDocument doc = new PdfDocument("VisibleSignature.pdf");
// 文書からフォームウィジェットを取得
PdfFormWidget widgets = doc.Form as PdfFormWidget;
// ウィジェットを走査
for (int i = 0; i < widgets.FieldsWidget.List.Count; i++)
{
PdfFieldWidget widget = widgets.FieldsWidget.List[i] as PdfFieldWidget;
// 署名フィールドかどうかを判定
if (widget is PdfSignatureFieldWidget)
{
widgets.FieldsWidget.RemoveAt(i);
}
}
doc.SaveToFile("RemoveSignatures.pdf");
}
}
}
このコードは正順ループで処理しています。署名フィールドが 1 つだけの文書では問題なく動作しますが、複数の署名フィールドが連続して存在する場合、RemoveAt(i) で要素を削除すると後続のインデックスが前に詰まり、直後の要素が走査されず削除漏れが発生する可能性があります。複数署名を確実に削除したい場合は、ループを逆順(for (int i = widgets.FieldsWidget.List.Count - 1; i >= 0; i--))にするか、削除対象を別リストに集めてから除去する実装が安全です。
実装時の注意点
証明書の管理:署名に使用する PFX 証明書とそのパスワードは、コード内にハードコードせず、環境変数やシークレット管理サービスを通じて取得する設計が望ましいです。証明書が漏洩した場合、署名の信頼性が損なわれます。
署名の法的効力:デジタル署名の法的効力は、使用する証明書の発行元や準拠する法令によって異なります。業務用途で署名を付与する場合は、要件を満たす証明書を選択する必要があります。
削除の影響:署名を削除した PDF は、署名検証時に「未署名」または「改ざんの可能性」として扱われます。削除後の文書を再配布する場合は、再度署名を付与するか、削除の意図を関係者に共有しておくことが前提となります。
ライセンスの確認:本番環境で利用する場合は、使用するライブラリのライセンス条件を確認してください。無償版にはページ数制限があるほか、有償版でもライセンス形態によって配布可能な範囲が異なります。
まとめ
デジタル署名の追加は、証明書の読み込みと PdfSignature オブジェクトの設定を通じて行い、不可視署名と可視署名を用途に応じて選択できます。削除はフォームフィールドの走査と RemoveAt() による除去という流れで実装できます。署名の付与・削除はいずれも文書の真正性に関わる操作であるため、証明書の管理方法や削除後の扱いを含めた運用設計をあわせて検討することをお勧めします。