通常の電子署名は、PDF 文書のページ上に署名に関する何かしらの表示はなく、Acrobat の「署名」パネル内でのみ署名の確認が可能です。
ページ上に署名を表示するために、PLOP DS では、サインや印影などのグラフィックやテキストを用いて電子署名を付与することができます。
署名を検証するには、ページに埋め込んだサインや印影をクリックすれば可能です。
例えば、スキャンされた手書きの署名や、公的印鑑や企業のロゴや、署名用証明書の保有者の写真など、
文書の受け取った人が、その文書が署名されていると判断しやすいグラフィックやテキストを用いることができます。
この例では、読み込んだ PDF 文書のページの左下に
「Difitally signed yyyy/mm/dd at hh:mm:ss JST」という赤字のテキストを用いて電子署名を付与しています。
PDFlib を使って上記の赤文字テキストを表示した PDF を作成し、PLOP DS でこの赤文字テキストを用いて、PLOP DS で別途取込んだ PDF に電子署名を付与します。
下記の「出力結果」は、評価版の PDFlib を使用した結果であるため、上記の赤字テキストの背後に「www.pdflib.com」のロゴが表示されています。
(本番用としてライセンスキーを適用すると、このロゴは表示されません)
今回、赤文字テキストを含む PDF 文書を作成するため PDFlib を使用していますが、
作成する必要がない(別途、手書きの署名や公的印鑑などの PDF 文書ファイルの用意がある)場合は、PDFlib は必要ありません。
open_document() で用意した PDF 文書のハンドルを取得し、オプション field の visdoc サブオプションでそのハンドルを指定すれば、利用できます。
このサンプルで使用した電子署名は信頼された認証局で発行されたものではないため、Adobe Acorbat 等で開くと「少なくとも 1 つの署名に問題があります。」と表示されますが、信頼された認証局で発行された電子署名を使うと「署名済みであり、すべての署名が有効です。」と表示されます。
また、このサンプルでは、PLOP パッケージに含まれていない PDFlib 必要としますが、PDFlib の無償評価版を当社 Web サイトからダウンロードすることができます。
必要な製品:PDFlib PLOP DS 及び PDFlib
処理の流れ
①メモリ内に新規 PDF 文書を生成
begin_document() 関数で、メモリ内に新規PDF文書を生成します。
②PDF 文書ページを開く
① で作成した PDF 文書のページを open_page_ext() 関数を使用して開きます。
④署名用のテキストを出力する
ここでは fit_textline() 関数でテキストを出力しています。
fit_textline() 関数は、その引数で、テキストを出力する位置を指定できます。
また、fit_textline() 関数のオプションによって、使用したいフォントやフォントサイズ、文字色を指定することができます。
⑤PDF ページを閉じる ⑥PDF 文書を閉じる
署名用の文字列の設定が完了したら、end_page_ext() 関数を用いてPDF のページを閉じ、
さらに end_document() 関数を用いてPDF文書を閉じます。
ここまでで PDF の作成は完了し、次は作成した PDF に電子署名を付与します。
⑦メモリ内にある PDF 文書データを取得
get_buffer() 関数を使って、①~⑥で生成した PDF 文書のデータを変数に格納します。
この変数は、create_pvf() の引数で使用します。
⑧PVF(PDFlib Virtual File System )ファイルを生成する
create_pvf() 関数で PVF ファイルを生成します。
PVF とは、仮想の読み取り専用ファイルに名前を付けて、それを通常のファイル名と同じように扱えるというものです。
①~⑥で作成した PDF 文書は、取込んだ PDF への署名に必要なだけなので、PDF ファイルとして、ディレクトリ等のディスク上に出力する必要はありません。
PVF ファイルを使用することで、処理速度の向上を見込むことができます。
仮想ファイル名は任意に名づけることができますが、ディスク上のファイルと名前衝突が発生しないようにしなければなりません。
⑨電子署名を付与したい既存の PDF 文書を開く
open_document() 関数で、電子署名を付与したい既存のPDF文書を開きます。
※署名用の赤字テキストを含む PDF 文書ではありません
⑩PVFファイルを開く
open_document() 関数を使って、⑧ で生成した PVF ファイルを開きます。
PVF ファイルは、通常のディスク上のファイルと同様にあらゆる API で扱うことができるため、
open_document() 関数で開くことができます。
※ここで開くのは署名用の赤字テキストを含むファイルです。⑨ と ⑩ では開いているファイルが異なります。
⑪電子署名を作成する
prepare_signature() 関数で、オプションで指定したデジタル ID を用いて、電子署名を作成します。
digitalid オプションで使用するデジタル ID を指定します。
field オプションの visdoc サブオプションに ⑩ で取得したハンドルを指定します。
field オプションは、ページ上でその署名の表現を制御します。
署名用のテキストを含む PDF ファイルを、ページ上の配置する場所とその寸法を、rect サブオプションを用いて指定します。
⑫電子署名を PDF に付与して出力する
create_document() 関数で、⑪ で作成した電子署名を ⑨ で開いた PDF ファイルに付与し出力します。
⑬PDF 文書を閉じる
close_document() 関数で、⑫ で出力した PDF 文書を閉じます。
⑭PVF ファイルを閉じて、削除する
close_document() 関数で、⑧ で出力した PDF 文書を閉じます。
delete_pvf() 関数で ⑧ で生成した PVF ファイルを削除します。
ソースコードと出力結果
/*
* 手書き署名等の画像を用いた電子署名:
* サインや印影など、個人を特定できる署名の画像などを含む PDF 文書を、
* PDFlib と PLOP DS を用いて動的に生成する方法を示します。
* このサンプルには、PLOP パッケージに含まれていない PDFlib を必要としますが、
* PDFlib の無償評価版を当社 Web サイトからダウンロードすることができます。
*
* 必要な製品 : PDFlib PLOP DS 5 及び PDFlib 9
* 必要なデータ : demo_signer_rsa_2048.p12
* demo_signer_rsa_2048.p12 は data ディレクトリにあります。
* demo_signer_rsa_2048.p12 のパスワードは demo です。
*/
import java.io.*;
import com.pdflib.PLOPException;
import com.pdflib.plop;
import com.pdflib.PDFlibException;
import com.pdflib.pdflib;
import java.text.DateFormat;
import java.util.Date;
public class dynamicsign {
public static void main (String argv[]) {
pdflib pdf = null;
plop plop = null;
try {
byte[] contents;
Date now = new Date();
DateFormat fulldate = DateFormat.getDateInstance(DateFormat.LONG);
DateFormat fulltime = DateFormat.getTimeInstance(DateFormat.LONG);
String optlist;
int doc, visdoc;
/* 本サンプルに必要なデータが保存されているディレクトリを指定する */
String searchpath = "../data";
final String out_filename = "hellosign.pdf";
/* 基本的な署名オプション */
String sign_opts =
/* ltv オプション:長期検証(LTV)をするかどうかを指定する。
LTV を行う場合は full を指定する(デフォルト:try) */
"ltv=try " +
/* engine オプション:電子署名を作成するための暗号化エンジンを指定(デフォルト:builtin)
digitalid オプション:使用するデジタル ID を指定する
password オプション:デジタル ID に対するパスワード等を指定する */
"engine=builtin digitalid={filename=demo_signer_rsa_2048.p12} password={demo} ";
* 実行ファイルに渡す引数(取込む既存PDF名・出力するPDF名)のチェックを行う */
if (argv.length < 2) {
throw new Exception("usage: dynamicfile <infile> <outfilename>");
}
/* ----------- ステップ1: PDFlib を用いてメモリ内に動的に文書を生成します ---------- */
/* PDFlib オブジェクトを作成する */
pdf = new pdflib();
/* ①メモリ内に新規PDF文書を生成 */
pdf.begin_document("", "");
/* 文書の作成者やタイトル等、文書情報フィールドを設定する */
pdf.set_info("Creator", "dynamicsign.java");
pdf.set_info("Author", "Rainer Ploeckl");
pdf.set_info("Title", "Dynamic signature visualization document");
/* ②PDF 文書ページを開く */
pdf.begin_page_ext(300, 50, "");
/* ④署名用のテキストを出力する */
pdf.fit_textline("Digitally signed " + fulldate.format(now) +
" at " + fulltime.format(now), 10, 10,
"fontsize=10 fontname=Helvetica encoding=unicode fillcolor=red");
/* ⑤PDF ページを閉じる ⑥PDF 文書を閉じる */
pdf.end_page_ext("");
pdf.end_document("");
/* ⑦メモリ内にある PDF 文書データを取得 */
contents = pdf.get_buffer();
/* ----------- ステップ2 : PLOP DS を用いて文書に署名します ---------- */
/* PLOP オブジェクトを作成する */
plop = new plop();
/* 読み込みたいファイルの入ったディレクトリを指定する */
optlist = "searchpath {" + searchpath + "} ";
plop.set_option(optlist);
/* ⑧PVF(PDFlib Virtual File System )ファイルを生成する */
plop.create_pvf("/pvf/visdoc.pdf", contents, "");
/* ⑨電子署名を付与したい既存のPDF文書を開く */
if ((doc = plop.open_document(argv[0], "")) == -1) {
throw new Exception("Error: " + plop.get_errmsg());
}
/* ⑩PVFファイルを開く */
if ((visdoc = plop.open_document("/pvf/visdoc.pdf", "")) == -1) {
throw new Exception("Error: " + plop.get_errmsg());
}
/* ⑪電子署名を作成する */
optlist = sign_opts + " field={visdoc=" + visdoc + " rect={10 10 adapt adapt}} ";
if (plop.prepare_signature(optlist) == -1) {
throw new Exception("Error: " + plop.get_apiname()
+ ": " + plop.get_errmsg());
}
/* ⑫電子署名を PDF に付与して出力する */
if (plop.create_document(argv[1], "input=" + doc) == -1) {
throw new Exception("Error: " + plop.get_apiname()
+ ": " + plop.get_errmsg());
}
/* ⑬PDF文書を閉じる */
plop.close_document(doc, "");
/* ⑭PVFファイルを削除する */
plop.close_document(visdoc, "");
if (plop.delete_pvf("/pvf/visdoc.pdf") == -1) {
throw new Exception("Error: " + plop.get_errmsg());
}
} catch (PLOPException e) {
System.err.println("PLOP exception occurred in dynamicsign sample:");
System.err.println("[" + e.get_errnum() + "] " + e.get_apiname() +
": " + e.get_errmsg());
} catch (PDFlibException e) {
System.err.println("PLOP exception occurred in dynamicsign sample:");
System.err.println("[" + e.get_errnum() + "] " + e.get_apiname() +
": " + e.get_errmsg());
} catch (Exception e) {
System.err.println(e);
} finally {
/* PLOP オブジェクトを削除する */
if (plop != null) plop.delete();
/* PDFlib オブジェクトを削除する */
if (pdf != null) {
try {
pdf.delete();
} catch (Exception e) {
System.exit(2);
}
}
}
}
}