複数の PDF 文書に PKCS#11 で署名を付与
PLOP DS は、PDF 文書に署名するためにはデジタル ID を必要とし、以下のデジタル ID を使用できます。
使用するデジタル ID に合わせて engine オプションの値を指定します。
・PKCS#12 形式のデジタル ID ファイル engine オプション:builtin
・暗号トークンに保管されているデジタルID engine オプション:pkcs#11
・Windows 証明書ストア内のデジタル ID engine オプション:mscapi ※Windows のみ
このページでは、PKCS#11 エンジンを利用し、
上記二番目の「暗号トークンに保管されているデジタルID」で電子署名を作成し、複数の PDF に付与する方法を説明します。
prepare_signature() 関数で使用するオプションで、以下の2つのオプションを設定します。
・engine=pkcs#11:電子署名を作成するためのエンジンを pkcs#11 に指定
・digitalid={filename=cryptoki.dll}:ベンダー固有の PKCS#11 DLL を指定
PKCS#11 エンジンを利用すると、スマートカード・USBスティック等の暗号トークンや、
ハードウェアセキュリティモジュール(HSM)にあるデジタル ID を使用できます。
このような機器を使用して署名を作成するには、トークン個別のプロトコルを実装した DLL ファイルや共有ライブラリが必要です。
この DLL ファイルなどは、そのトークンのプロパイダーによって提供されるもので、
これらのファイルがシステムにインストールされ、PLOP DS から利用可能になっている必要があります。
今回の例では、cryptoki ライブラリを使用するため、digitalid オプションの filename サブオプションで cryptoki.dll を指定していますが、
実際の DLL 名は今回の例と異なる可能性があり、適宜変更する必要があります。
また、暗号トークンに対してパスワードなどを入力する必要がある場合には、password 署名オプションを与える必要があります。
このサンプルで使用した電子署名は信頼された認証局で発行されたものではないため、Adobe Acorbat 等で開くと「少なくとも 1 つの署名に問題があります。」と表示されますが、信頼された認証局で発行された電子署名を使うと「署名済みであり、すべての署名が有効です。」と表示されます。
必要な製品:PDFlib PLOP DS
処理の流れ
①電子署名を作成する
prepare_signature() 関数で、オプションで指定したデジタル ID を用いて電子署名を作成します。
②既存の PDF 文書を開く
open_document() 関数を使って、電子署名を付与したい既存の PDF ファイルを開きます。
③電子署名を PDF に付与して出力する
create_document() 関数で、② で作成した電子署名を ① で開いた PDF に付与し、PDF を出力します。
④PDF文書を閉じる
close_document() 関数で、PDF 文書を閉じれば、電子署名の付与は完了します。
⑤②~④までの処理を電子署名を付与したいPDFの文書分繰り返す
ソースコードと出力結果
/*
* 複数の PDF 文書に PKCS#11 で署名を付与:
* 複数の PDF 文書に電子署名を行う方法を示し、PKCS#11 トークンのためのセッション処理を演示します。
*
* 必要な製品 : PDFlib PLOP DS 5
* 必要なデータ : demo_signer_rsa_2048.p12
* demo_signer_rsa_2048.p12 は data ディレクトリにあります。
* demo_signer_rsa_2048.p12 のパスワードは demo です。
*/
import java.io.*;
import com.pdflib.plop;
import com.pdflib.PLOPException;
public class multisign {
public static void main (String argv[]) {
plop plop = null;
/* 基本的な署名オプション */
String sign_opts =
/* ltv オプション:長期検証(LTV)をするかどうかを指定する。
LTV を行う場合は full を指定する(デフォルト:try) */
"ltv=try " +
/* engine オプション:電子署名を作成するための暗号化エンジンを指定
digitalid オプション:暗号トーク ンに対する PKCS#11 DLL/共有ライブラリの名前を指定 */
"engine=pkcs#11 digitalid={filename=cryptoki.dll}";
boolean PKCS11 = false;
try {
/* 既存 PDF に関する変数を用意する */
String optlist;
String signed_name = "";
String searchpath = "../data";
int doc;
int i;
/* 実行ファイルに渡す引数(取込む既存 PDF 名)のチェックを行う */
if (argv.length < 1) {
throw new Exception("usage: sign <infile> ...");
}
/* PLOP オブジェクトを作成する */
plop = new plop();
/* 読み込みたいファイルの入ったディレクトリを指定する */
optlist = "searchpath {" + searchpath + "} ";
plop.set_option(optlist);
/* ①電子署名を作成する */
if (plop.prepare_signature(sign_opts) == -1) {
throw new Exception("Error: " + plop.get_apiname() + ": " + plop.get_errmsg());
}
PKCS11 = true;
/* 取込みたい PDF 文書の数分、処理を繰り返す */
for (i = 0; i < argv.length; i++){
System.out.println("Signing '" + argv[i] + "'");
/* ②既存の PDF 文書を開く */
if ((doc = plop.open_document(argv[i], "")) == -1) {
System.err.println("Error: " + plop.get_apiname() + ": " + plop.get_errmsg());
continue;
}
/* 電子署名付与後のファイル名を指定する */
signed_name = argv[i] + "-signed.pdf";
/* ③電子署名を PDF に付与して出力する */
if (plop.create_document(signed_name, "input=" + doc) == -1) {
System.err.println("Error: " + plop.get_apiname() + ": " + plop.get_errmsg());
if (PKCS11){
if (plop.prepare_signature(optlist) == -1) {
throw new Exception("Error: " + plop.get_apiname()
+ ": " + plop.get_errmsg());
}
if (plop.create_document(signed_name, "input=" + doc) == -1) {
throw new Exception("Error: " + plop.get_apiname()
+ ": " + plop.get_errmsg());
}
}
}
/* ④PDF文書を閉じる */
plop.close_document(doc, "");
}
} catch (PLOPException e) {
System.err.println("PLOP exception occurred in multisign 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();
}
}
}