公証人に認証された電子署名済みの電磁的記録を検証する

# はじめに

## 経緯

私個人が作成・電子署名したPDF形式の電子文書を、公証役場の公証人に認証してもらい、認証済みの文書一式を受け取りました。ただ、この文書は本当に私が作成したものなのか、また本当に公証人が認証したものなのか、検証する方法が一見して分からなかったので、検証方法を調査しました。なお、私は士業ではありません。

## 筆者の環境

* Acrobat Reader DC
* Cygwin
 * openssl 1.0.2k
 * xmlsec1 1.2.24
* Windows 10 Pro 64ビット

# 作成者の署名の検証

## 証明書と署名の検証

PDFは、個人番号カード（マイナンバーカード）に入っている署名用電子証明書により電子署名されたものです。この証明書の発行者は地方公共団体情報システム機構の公的個人認証サービス署名用認証局であり、これはルートCAです。すなわち、発行者の証明書は自己署名証明書となります。

発行者の証明書は、マイナンバーカード自体に収められていて、地方公共団体情報システム機構が提供する利用者クライアントソフトで取り出せるほか、同機構公的個人認証サービスポータルサイトで、[署名用認証局の運営に関する情報](https://www.jpki.go.jp/ca/ca_rules3.html)として配布されています。なお、同サイトが改ざんされ、不正な証明書を手に入れてしまう可能性がありますので、証明書の拇印（フィンガープリント）を確認するなどしたほうがよいでしょう。現時点のSHA-1拇印は以下のとおりです。

```
‎95 2c cd c9 4d f8 f4 02 e0 8e e5 6c 30 9d 51 89 05 e7 71 46
```

PDFの署名の検証では、署名者の証明書が、信頼できる発行者から発行されたものかどうかを検証する必要がありますが、通常、地方公共団体情報システム機構の署名用認証局の証明書はAdobe Acrobat Readerに信頼済み証明書として登録されていないので、まずはその登録を行います。Adobe Acrobat Readerから[編集]-[環境設定]-[署名]-[IDと信頼済み証明書]-[信頼済み証明書]から取得したルートCA証明書を取り込み、その証明書について[信頼性の編集]で[この証明書を信頼済みのルートとして使用]にチェックを入れます。

![](https://qiita-image-store.s3.amazonaws.com/0/12670/3a060f7b-bec3-07ef-413a-5e57d2905f1d.png)

これにより、Adobe Acrobat ReaderでPDFファイルを開くと、「署名済みであり、全ての署名が有効です。」と表示されます。そして、電子署名に対する証明書も表示できます。

ただ、署名を行った証明書の主体（サブジェクト）がなんらかのシリアルナンバーになっており、氏名などの情報が無いので、この段階では、地方公共団体情報システム機構の署名用認証局が発行した証明書により、誰かが署名をしたと言うことしか分かりません。

## 署名した個人を特定

署名した個人を特定する情報は証明書のX509v3 Subject Alternative Nameと呼ばれる項目に入っていますが、Adobe Acrobat Reader上は確認できないので、opensslコマンドにより確認します。

まず、署名者の証明書をファイルに書き出します。通常DER形式になっているので、opensslで処理するために、PEM形式に変換します。

```shell-session
$ openssl x509 -in yourcert.cer -inform DER -out yourcert.pem -outform PEM
```

次に、PEM形式の証明書にASN.1でエンコードされた内容を表示します。`{}`で囲んだ部分は記事上では伏せています。

```shell-session
$ openssl asn1parse -in yourcert.pem
{略}
625:d=5  hl=2 l=   3 prim: OBJECT            :X509v3 Subject Alternative Name
630:d=5  hl=3 l= 229 prim: OCTET STRING      [HEX DUMP]:{}
{略}
```

X509v3 Subject Alternative NameのOBJECTに続くOCTET STRINGのオフセット値（上記例の場合630）を調べ、さらに文字列としてダンプさせると、氏名等を確認できます。

```shell-session
$ openssl asn1parse -strparse {オフセット値} -in yourcert.pem
    0:d=0  hl=3 l= 226 cons: SEQUENCE
    3:d=1  hl=2 l=  31 cons: cont [ 0 ]
    5:d=2  hl=2 l=  10 prim: OBJECT            :1.2.392.200149.8.5.5.1
   17:d=2  hl=2 l=  17 cons: cont [ 0 ]
   19:d=3  hl=2 l=  15 prim: UTF8STRING        :{姓}　{名}
   36:d=1  hl=2 l=  25 cons: cont [ 0 ]
   38:d=2  hl=2 l=  10 prim: OBJECT            :1.2.392.200149.8.5.5.4
   50:d=2  hl=2 l=  11 cons: cont [ 0 ]
   52:d=3  hl=2 l=   9 prim: UTF8STRING        :{XYYYYMMDD形式の生年月日。数字Xの意味は不明}
   63:d=1  hl=2 l=  17 cons: cont [ 0 ]
   65:d=2  hl=2 l=  10 prim: OBJECT            :1.2.392.200149.8.5.5.3
   77:d=2  hl=2 l=   3 cons: cont [ 0 ]
   79:d=3  hl=2 l=   1 prim: UTF8STRING        :{性別。男性が1？}
   82:d=1  hl=2 l=  82 cons: cont [ 0 ]
   84:d=2  hl=2 l=  10 prim: OBJECT            :1.2.392.200149.8.5.5.5
   96:d=2  hl=2 l=  68 cons: cont [ 0 ]
   98:d=3  hl=2 l=  66 prim: UTF8STRING        :{住所}
  166:d=1  hl=2 l=  21 cons: cont [ 0 ]
  168:d=2  hl=2 l=  10 prim: OBJECT            :1.2.392.200149.8.5.5.2
  180:d=2  hl=2 l=   7 cons: cont [ 0 ]
  182:d=3  hl=2 l=   5 prim: UTF8STRING        :{氏名代替文字の使用情報。各桁について、0が通常、1が代替文字？}
  189:d=1  hl=2 l=  38 cons: cont [ 0 ]
  191:d=2  hl=2 l=  10 prim: OBJECT            :1.2.392.200149.8.5.5.6
  203:d=2  hl=2 l=  24 cons: cont [ 0 ]
  205:d=3  hl=2 l=  22 prim: UTF8STRING        :{住所代替文字の使用情報。各桁について、0が通常、1が代替文字？}
```

なお、Adobe Acrobat Readerで確認済みですが、openssl上でこの署名が地方公共団体情報システム機構の署名用認証局により発行されたものか検証するには、以下を実行します。`jpki.pem`には、PEM形式にした地方公共団体情報システム機構の署名用認証局の証明書を指定してください。念のため`jpki.pem`の部分を別の証明書にして、検証が失敗することを確認するのも良いと思います。

```shell-session
$ openssl verify -CAfile jpki.pem yourcert.pem
yourcert.pem: OK
```

以上で、X509v3 Subject Alternative Nameに記載された住所氏名で特定される個人が、PDFファイルに署名を行ったことを検証できました。

## 作成者の署名が失効していた場合

なお、地方公共団体情報システム機構が発行した証明書の失効情報は、「電子署名等に係る地方公共団体情報システム機構の認証業務に関する法律」第17条第1項により、一般人には提供されません。よって、以下の理由等で失効した証明書により署名が行われた可能性は残ります。

*公的個人認証サービス 署名用認証局 運用規程 第 1.1 版 より*

> ```
>（1） 署名利用者の申請又は届出に基づく失効の事由
> 署名利用者が行う署名用電子証明書の失効の事由は次のとおりである。
> ・ 署名利用者が本サービスの利用を取りやめる旨の申請があった場合
> ・ 署名利用者の秘密鍵が漏洩し、滅失し、若しくは毀損したとき、又は署名用電子証明書を格納した個人番号カードが使用できなくなった旨の届出があった場合
> （2） 市区町村長が行った情報の記録による失効の事由
> 市区町村長が行った情報の記録による署名用電子証明書の失効の事由は次のとおりである。
> ・ 署名利用者の住民票の記載事項（基本4情報等）の修正が発生した場合（総務省令で定める軽微な修正を除く）
> ・ 署名利用者の署名用電子証明書に記載された事項について、当該電子証明書の発行を受けた署名利用者に係る住民票に記載されている事項と異なるものが発見された等の記録誤り又は記録漏れがあった場合
> ・ 住民票が消除された場合
> （3） 機構が行う失効の事由
> ・ 署名用CAの秘密鍵が危殆化した場合
> ```

失効証明書の確認ができないのは残念ですが、実印及び印鑑登録証明書においても、法的側面はともかく、無効になった実印と取得済みの印鑑登録証明書を使うことは物理的には可能なので、セキュリティレベルが実印より落ちるわけでは無いと言えると思います。

# 公証人による認証の検証

## ファイル構成

公証人による認証が行われた電磁的記録は、以下のファイルで構成されます。

* XMLファイル
 * 認証に関する情報
* XSLファイル
 * XMLファイルを表示用のHTMLに変換するためのXSLT
* PDFファイル
 * 認証対象の文書

以下、XMLファイル内を確認していきます。

## XMLファイルの形式

XMLファイルには、電磁的記録の認証に関する表示用の文言の他、[W3Cの規定によるXML署名](https://www.w3.org/TR/xmldsig-core/)が含まれています。

```xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="{}.xsl"?>
<DOC VERSION="1.0">
    <FRONT>
        <SECRECY>普通</SECRECY>
        <STAMP>要</STAMP>
    </FRONT>
    <BODY ID="DOCBODY">
        <STYLESHEET URI="{}.xsl"/>
        <TITLE>電磁的記録の認証</TITLE>
        <MAINTXT>
            <P LEVEL="0">{申請番号} </P>
            <P LEVEL="0">{}年{}月{}日 </P>
            <P LEVEL="0">{登簿管理番号} </P>
            <P LEVEL="0">{公証人氏名} </P>
            <P LEVEL="0">{法務局名称} </P>
            <P LEVEL="0">{公証役場名称} </P>
            <P LEVEL="0">{公証役場住所} </P>
            <P LEVEL="0"> </P>
            <P LEVEL="0"> </P>
            <P LEVEL="0"> </P>
            <P LEVEL="0">　 </P>
            <P LEVEL="0"> </P>
            <P LEVEL="0"> </P>
            <P LEVEL="0"> </P>
            <P LEVEL="0"> </P>
        </MAINTXT>
        <MAINTXT2>
            <MT2TITLE>記</MT2TITLE>
            <MT2TEXT>
                <P LEVEL="0">嘱託人は、この電磁的記録に記録された情報に電子署名をしたことを自認する旨を本職の面前で陳述した。よって、これを認証する。 </P>
            </MT2TEXT>
        </MAINTXT2>
    </BODY>
    <APPENDIX ID="moj.go.jp">
        <DOCLINK REF="{}.pdf"/>
    </APPENDIX>

<Signature Id="{}" xmlns="http://www.w3.org/2000/09/xmldsig#">
  <SignedInfo>
    <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
    <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
    <Reference URI="#DOCBODY">
      <Transforms>
        <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
      </Transforms>
      <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
      <DigestValue>{}</DigestValue>
    </Reference>
    <Reference URI="{}.pdf">
      <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
      <DigestValue>{}</DigestValue>
    </Reference>
  </SignedInfo>
  <SignatureValue>{}</SignatureValue>
  <KeyInfo>
    <X509Data>
      <X509Certificate>{}</X509Certificate>
      <X509Certificate>{}</X509Certificate>
    </X509Data>
  </KeyInfo>
</Signature>
</DOC>
```

## 証明書の検証

まず、XMLファイル内に公証人の証明書、およびそれを発行した認証局の証明書が入っているので、それらを取り出します。証明書は、 `/Signature/KeyInfo/X509Data/X509Certificate` 内にbase64エンコードされたDER形式で入っています。以下のコマンドで取り出せます。

```shell-session
$ echo '{1つ目のX509Certificateのテキスト}' | base64 -d > notary1.cer
$ echo '{2つ目のX509Certificateのテキスト}' | base64 -d > notary2.cer
```

どちらかが公証人の証明書で、もう一方はそれを発行した政府認証基盤の官職認証局の証明書のはずです。官職認証局はルートCAなので、証明書は自己署名証明書となります。

公証人の証明書の主体（サブジェクト）は次のようになっており、どの公証役場で公証されたかを特定できます。公証人の番号は入っていますが、公証人の氏名の情報は入っていません。

```
CN = Notary{2桁の数字}
OU = {} Notary Office
OU = {} Legal Affairs Bureau
OU = Ministry of Justice
O = Japanese Government
C = JP
```

もちろんXMLファイルから取り出した認証局の証明書は信頼できないので、官職認証局の自己署名証明書を[政府認証基盤のページ](https://www.gpki.go.jp/selfcert/self_cert.html)等から入手し、偽造されたもので無いことを拇印で確認して、Windowsに信頼できるルート証明機関としてインストールします。現時点でのSHA-1拇印は以下のとおりです。

```
‎93 9d d7 0a c3 a7 ab 14 81 29 95 03 40 42 de 5c 1d ca 86 81
```

これによって、公証人の証明書をWindowsで表示した際、「この証明書は問題ありません。」と表示されれば、この証明書は確かに政府認証基盤から発行された証明書であると確認できます。

また、署名の検証時に使用するので、官職認証局の証明書をPEM形式に変換しておきます。

```shell-session
$ openssl x509 -in gpkiofficial.cer -inform DER -out gpkiofficial.pem -outform PEM
```


なお、政府認証基盤の官職認証局の証明書失効リストの取得先は不明でした。よって、公証人の証明書が失効している可能性は残ります。

## 署名の検証

次に、上記証明書により署名が行われたかどうかを確認します。署名の対象は、PDFファイル、およびXMLファイルのBODY要素内です。

これら署名対象のSHA-256ダイジェストが`Signature/SignedInfo`内に含まれており、この要素を公証人のRSA秘密鍵で暗号化したものが、署名として`Signature/SignatureValue`内に保存されています。

署名を検証するには、この署名を証明書内のRSA公開鍵で復号して、求めたダイジェストを含む`Signature/SignedInfo`と一致するか確認する必要があります。以下のコマンドで実行できます。`gpkiofficial.pem`には、PEM形式に変換した官職認証局の証明書を指定してください。XMLファイル内から相対パスでPDFファイルへの参照がされているので、XMLファイルのあるディレクトリで実行する必要があります。念のため署名対象のPDFを別のファイルにして、検証が失敗することを確認するのも良いと思います。

```shell-session
$ xmlsec1 --verify --xxe --id-attr:ID BODY --trusted-pem gpkiofficial.pem your.xml
OK
SignedInfo References (ok/all): 2/2
Manifests References (ok/all): 0/0
```

以上で、PDFファイル、およびXMLファイルのBODY要素内に対して、官職認証局が発行した公証人の証明書で署名されたことが確認できました。

# まとめ

公証人に認証された電磁的記録に対して、対象文書に対する作成者の署名の確認と、それに対する公証人の署名の確認をすることができました。失効証明書の確認ができない問題はありましたが、実印を用いた従来の公証と比べてセキュリティレベルが落ちているわけでは無いことも確認できました。ただ、この手順をソフトウェア技術に詳しくない方が行うのは困難かもしれません。

# 懸念

現時点で、マイナンバーカードの署名用電子証明書を用いた電子公証の事例は少ないようです。公証人の認証作業の過程は分かりませんが、Acrobat Readerの標準のUI上では、署名用電子証明書が正規のものであることは確認できても、その証明書の主体（サブジェクト）がシリアルナンバーになっており、住所氏名までは確認できないため、公証人が嘱託人ではない第三者の証明書で署名された文書を認証してしまうことが無いのか、気になるところです。（行政書士等の士業用の電子証明書の場合は、主体（サブジェクト）にローマ字の氏名が入っています）。

「嘱託人は、この電磁的記録に記録された情報に電子署名をしたことを自認する旨を本職の面前で陳述した。よって、これを認証する。」の文言が、対象文書と共に公証人によって電子署名されているので、万が一文書作成者の電子署名が他者のものであっても、法的な証明力には問題ないのかもしれません。