PDF の電子署名(certificate, digitally sign)の仕組みと電子締結運用のメモ

## 背景

法人と法人, もしくは法人が主体となり法人と個人とで電子契約をする(法人は法人代表印を代替する商業登記に基づく電子署名を行う)

商業登記に基づく証明書で, PDF に電子署名し, 真贋性と, その法人が本当に作成した(承認した) PDF であることをやりたい.

商業登記電子証明書(法人印鑑証明書の電子化みたいなもの)のメモ
https://qiita.com/syoyo/items/831ffa7950c814602ada

「商業登記に基づく電子認証制度」の解説—法人代表者の実印と同等の法的効力を持つ電子署名を実施する方法
https://www.cloudsign.jp/media/20181227-denshisyomei-houjin/

ちなみに, macOS Preview や, Acrobat で署名(`signature`, `sign`)の機能がありますが, これは**画像データをスキャンして単に PDF に画像データとして付与するというなんちゃって署名機能**で, なんら技術的な裏付けのない署名方法になります(本人性, 改ざんされていないなどは担保されない)

Acrobat Reader, Acrobat DC では, 電子署名の機能は `Certificate` という名称になっています.

Acrobat Reader でも, 電子署名する機能があります. ただし, 複数の署名フィールドを作ることはできない + 後述する MDP 署名はできません. Acrobat Reader でも実務的にも, 技術的にも運用する上では問題はないと思われますが, 
フォームフィールドを生成したり, "部長の印, 経理部の印, 会社の印" みたいな複数承認欄を持つ書類を実現したいですと, Acrobat DC(最近は Adobe Acrobat Pro DC?)が必要になります.
(あとは, Linux とかのツールで頑張って署名フィールドを作るか)

### マイナンバーカードで電子署名は?

個人に対しては,技術的には, マイナンバーカードの電子証明書で電子署名も同じようにできるはずですが, マイナンバーカードの電子証明書を扱える(署名を検証できる)のは, 総務大臣により認定された事業者だけになっており, 事業者が勝手に使うとたしか違法になってしまいます. :cry:

https://www.soumu.go.jp/kojinbango_card/kojinninshou-02.html

電子署名法自体では, 署名検証認定事業者は不要ですが, マイナンバーカードの場合は個人情報保護法とかほかの法律でなにか縛りがあるのかもしれません.

電子署名とは —電子署名法の基礎知識
https://www.cloudsign.jp/media/20180803-denshisyomeihou/

マイナンバーカードの電子証明書の公開鍵を得るだけというのもダメっぽそう?. はやく, 幅広く民間事業者がマイナンバーカードの電子署名を利用できるように規制緩和してほしいですね.


## PDF の電子署名の基本情報

ISO 32000に準拠するPDFってどんなもの？
https://www.antenna.co.jp/pdf/reference/iso32000-conformance.html

PDF v1.7
https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/PDF32000_2008.pdf

12.8 Digital Signatures になります.


PDF文書を対象にした電子署名／タイムスタンプ技術の実装例
～Acrobat Reader/Adobe Acrobat/Adobe Sign～
https://www.soumu.go.jp/main_content/000600453.pdf


PDFと署名(28) — PDFの2種類の署名
https://blog.antenna.co.jp/PDFTool/archives/2007/05/16/

https://www.adobe.com/devnet-docs/etk_deprecated/tools/DigSig/Acrobat_DigitalSignatures_in_PDF.pdf

電子署名の部分については,  ETSI のドキュメント(拡張仕様?)を見るのがよさそうです.

https://ja.wikipedia.org/wiki/PAdES

Electronic Signatures and Infrastructures (ESI);
PDF Advanced Electronic Signature Profiles;
Part 4: PAdES Long Term - PAdES-LTV Profile
https://www.etsi.org/deliver/etsi_ts/102700_102799/10277804/01.01.01_60/ts_10277804v010101p.pdf

## PDF v1.7 仕様の読解

以下は, とりあえず仕様を日本語訳した感じです.

ドキュメントのダイジェスト(digest, hash)を計算し(電子署名のデータ領域は除く), 署名してダイジェストを格納. 検証するときはドキュメントのダイジェストを再計算し, 格納されているダイジェストと一致するかどうか調べる.

ダイジェストには二種類ある.

ひとつは `ByteRange` エントリで指定されたデータ範囲を使ってダイジェストを計算する. `ByteRange` には signature の領域も含むが, その署名のデータ値(`Contents` エントリ)は考慮しない.

もう一つは付加的なもので, signature reference dictionary で修正の検出を行う. `TransformMethod` と `TransformParams` エントリを使って指定する(=> ダイジェストの計算方法になにか影響があるのかな?).

**approval signature**(承認用署名?) は複数持たせることができる. これらの signature は “Signature Fields” に存在する. signature directory は, 上記ダイジェストのように `ByteRange` entry を含んでいる必要がある.

ドキュメントが incremental update で修正, 保存されたとしても, 元の signature の byte range は変更されない. これにより, 署名があったときのドキュメントの状態を復元することができる.

**certification signature**(PDF 1.5) は最大 1 つ.  certification signature の signature directory は signature field の値でなければならず, また `ByteRange` エントリを含んでいなければならない. 
 
permissions ディレクトリの `DocMDP` エントリで参照される. MDP = modification detection, protection

signature ディレクトリは. `DocMDP` transform method を持つ signature reference ディレクトリを含んでいなければならない.

certification signature or approval signature の signature ディクショナリーは `FieldMDP` transform method を含んだ signature reference dictionary を持つことができる.

最大で 2 つの usage rights(利用権限?) signature(PDF 1.5). この signature dictionary は, permissions dictionary の `UR3`(PDF 1.6) エントリから参照される. signature dictionary は `Reference` エントリを持つ. この値は `UR` transform method を含んだ signature reference dictionary となる.

UR = user rights

  
`DocMDP` transform method は, ドキュメントの作者(最初に署名を付与した人物)により署名された signature field の修正を検出するために利用される. これはドキュメントに署名後どのような変更が許可され, どのような変更が NG になるのかを指定するのを可能にする.

PDFと署名(28) — PDFの2種類の署名
https://blog.antenna.co.jp/PDFTool/archives/2007/05/16/


### 電子署名のパターン

* 最初の署名者(通常, 法人の商業登記に基づく電子証明書で署名されている): certification signature, MDP 署名.
  * Adobe Acrobat DC で言う Certificate. Acrobat Reader には存在しない)
* 相手方などの署名: approval signature
  * Adobe Acrobat DC で言う Digital sign. Acrobat Reader にあり.

とします.

PDFと署名(26) — Adobe Readerによる署名されたPDFの検証
https://blog.antenna.co.jp/PDFTool/archives/2007/05/14/

での (2) が certification signature, (3)が approval signature になります.

以下は, Adobe Acrobat DC で作った PDF で動作を確認しました(本当は上記仕様をもう少し読み込んだほうがいいですね)

大きく分けて 4 パターンあります.

#### パターン 1(Certificate 署名)

まず, 一番よくあるであろうパターンが, 署名フィールド(紙でいう押印欄)が 1 つで, そこに MDP 署名(certification signature)をするものです.
紙で言えば, 登記事項証明書や印鑑証明書など, 発行者の印だけが押されている(+ 偽造防止印刷)文書に相当します.

署名フィールドは可視、不可視の設定ができますが, 技術的にはどちらも変わりありませんので, ひとまず可視かどうかは省きます.
(細かいところでは, 署名フィールドごとにいくつかパラメータを設定したり, 署名されたらスクリプト(!)を実行するとかが本来はできます)

この場合, その後の文章の改変(履歴の追加)は不可になります. Form field やコメント, 署名フィールドへの署名(approval signature)については, 許可する場合(Adobe Acrobat DC だとどこまで許可するかを指定して, 電子署名します)は利用可能になります.

ただし, **改変には電子署名の付与も含まれます**ので, 署名フィールドが一つで Certificate 署名がほどされている場合, "署名フィールドへの署名"の permission があったとしても, 他のひとがあとから電子署名(approval signature)を付与することもできません. timestamp の付与も不可です.
(Acrobat DC 上では permission の選択ができてしまうので, 違和感ありますが)

Certificate 署名だけの PDF はこんな感じになります.

![sigonly.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/91f9e912-db2b-5ea2-9e37-424c734900ca.png)

Certificate signature の場合は, リボンのロゴになっています.

#### パターン 2(複数署名フィールド)

次に, 複数の署名フィールド(approval signature 用)を作成し, 通常署名をどれか一つに行った場合. 
自署の捺印して, 相手側の署名(or 各部署のサイン)を求めるような文書ですね.

この場合, MDP 署名はできないようです. また, 電子署名のときに Form field やコメント, 署名フィールドへの署名の許可は出てきません. 改変可として取り扱われます.

approval signature の付与(e.g. 相手方が電子署名する)や timestamp の付与は差分(incremental update)として取り扱われます.

このとき, すこし不思議なのは, 作成した署名フィールド以外に approval signature の付与ができる点です.

![sign-3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/5a302a92-0f72-be31-2c41-9d2f71687c1f.png)

この例では, 右側に署名フィールドを二つつくり, 右下に最初の署名をしています. しかし, ユーザーは自由に approval signature を追加付与できます(左上. 簡単のために署名は一つを使いまわしています).

一応, 用意した署名フィールドには署名がされていない表示が出ますので, ここをチェックして, きちんと有効な(?)署名がされるかを確認するとなるでしょうか.

#### パターン 3(通常電子署名のみ)

MDP 署名ではなく, 通常電子署名(approval signature. Acrobat で言う Digitally sign)した場合. これは基本パターン 2 と同じです. 署名フィールドが一つであっても, その後電子署名を追加で付与したりできます.

#### パターン 4(MDP 署名をいったん削除して, 通常署名付与)

最後が, (Acrobat DC を使って生成する上で)少し面白いパターンです. 

パターン 1 の MDP 署名を施した PDF は改変+電子署名/timestamp の追加付与はできないのですが, これを可能にするものとして, いったん署名を削除し(Acrobat DC だと, Visible certificate の場合, 署名フィールド右クリック ->  `Clear Signature` で署名を除去できます), 再度通常署名するというのです.
(ただし, Acrobat DC で署名後変更不可にしている場合のみ, Acrobat reader などではひっぺがせない)

また, Acrobat DC では, ひっぺがしたあとに Certificate 署名を再度行うことはできませんでした.

内部的には, 未署名のオリジナル + 差分として approval signature という構成の PDF になっているようです(たぶん. `%%EOF` 数を見ると 2 つであった).

![sig-rev.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/4b17352e-b414-8f2e-bdad-cd65f047e3a1.png)
 
オリジナルのバージョンは, `Click to view this version` で確認できるようになります 

また, 最後の署名者は, これ以上の変更は受け付けないと言う形で, 署名後に lock することもできます(実務上は timestamp を付与してロック, でしょうか)

##### 署名の除去?

ここで気になるのは, パターン 1 で生成された MDP 署名の除去は. だれでもできる(他ユーザーが, MDP 署名のある PDF を Acrobat Reader や Acrobat DC で削除できる)ということです. 誰でも(何かしら悪意のある第三者)が, MDP 署名をひっぺがして, 自分の(approval)署名を付与できてしまいます.
(ただ, Acrobat reader では, MDP 署名で変更不可モードになっている時だけはひっぺがせないが, 複数署名対応したいときはこのモードにはしないので, 実質ひっぺがせると考えてよいのではないでしょうか)

技術的には, 証明書のチェック, revision や hash を見て, 真正性や改竄されているかどうか判断すればいいですが, 
裁判で紙で印刷して証拠物提出など, 見た目で書類が判断するようなときに面倒そうな気がします.

たとえば, 悪意ある第三者が, 他のところで締結された契約書をコピってきて, 自分の署名(可視の電子署名にして, 印鑑はスキャンし画像で付与!)に変えたりとか.

電子署名の場合は不可視をデフォルト(印鑑画像があったら無効とみなす)にしたり, 契約書にはフォームフィールドなどをつくらず, 全部記載してから MDP 署名するとか, にするといいかも?

## PDF のなかみ

より深く署名の履歴や改変部分をチェックしたい場合は, PDF を直接扱うことになります.

PDF は, 基本的には構造化された ASCII text になります(画像とかはバイナリ形式なので, テキストエディタではそのままではいくつか文字化けする)

PDF のフォーマットなどは他にいろいろとよい記事がありますので, そちらを参考ください. たとえば...
  
詳細PDF入門 ー 実装して学ぼう！PDFファイルの構造とその書き方読み方
https://itchyny.hatenablog.com/entry/2015/09/16/100000


## タイムスタンプについて

昨今においては, ビットコインのブロックチェーンを使った, decentralized で reliable なタイムスタンプがありますが

https://opentimestamps.org/

現状, 日本国の法律においては, **日本データ通信協会の認定したタイムスタンプ事業者が発行したタイムスタンプ**でないと法的に認められないケースがあります(e.g. 電子帳簿保存法など)

これらのタイムスタンプサービスを普通に使おうとすると, だいたい月に基本月額だけで 1 万円くらいはかかります. アパート賃貸契約や, 半年 ~ 1 年続くようなプロジェクトの契約書を電子締結するときになど, 利用頻度が年数回のようなケースにはちょっと向かないですよね.

https://www.e-timing.ne.jp/price/

また, Adobe がホスティングしている Adobe Sign では, 世界標準(?)の timestamp を使うことができるようですが, Adobe Sign サービス自体には **日本データ通信協会の認定したタイムスタンプ事業者が発行したタイムスタンプ** には対応していません.

## まとめ. 電子締結は PDF でいいのかしらん?

MDP 署名は, 複数人が署名(合意, 締結)する場合には, 原本のバージョンだけが真正であることを保証できるもので, 結局複数人の署名(+ timestamp)を付与する場合は差分で対応となります.

甲と乙, それぞれの電子署名をほどこして, ついでに timestamp も付けたのを原本にして, これ以外差分なしのオリジナルバージョンだけ! というのは PDF の仕組み上できませんでした.

そうなると, PDF(or word など, 紙でのレイアウトに近いもので契約を交わす)でそもそもいいのか, 電子署名による電子締結をわざわざ PDF でやるのか? という疑問が湧いてきます. 

結局 PDF の場合は差分での運用になってしまうのですから, 双方合意(or 複数人からの合意)を取って合意の記録を残すのが目的であれば, PDF や文章レイアウトにはこだわらず, テキスト(or Markdown)でいいのではないかという気もしてきます. 

テキストだと差分管理も出せますし, git で差分管理もできますし, PDF の差分解析, 検証の手間も減ります. 
(既存のワークフローに載せるため PDF に変換する必要も出てくるであろうが, PDF 上での電子署名はあまり重要では無い)

そこからさらにすすんで, 双方(or 複数人)での電子署名も, テキスト(Markdown)に対して pgp or ビットコインのブロックチェーンのように署名のチェーンを施すだけで十分ではないか, という気もしてきます. 

また, 見た目については, たとえば markdeep を使うことで, Markdown テキストそのままだけど, ブラウザで見たら html 表示してくれる, という手もありそうです.

https://casual-effects.com/markdeep/

## TODO

* [ ] Acrobat DC で電子署名付与するのめんどいので, PortableSigner あたりとかで Linux でバッチで処理したい.