署名と証明書の有効期限

# はじめに

#### 問：署名証明書の有効期限切れ＝署名の有効期限切れ…なのか？

　PKI（公開鍵基盤）ベースのX.509電子証明書（以後、証明書）を使ったデジタル署名の電子署名方式には有効期限があるのでしょうか？署名に使った証明書の有効期限が切れてしまった場合に、その署名は無効になるのでしょうか？

#### 答：署名証明書の有効期限切れ＝署名の有効期限切れ…とは限らない。

　デジタル署名の検証結果は「**有効/VALID**」と「**無効/INVALID**」の2種類と思われがちですが、実はその間に「**不明/INDETERMINATE**」と言う状態があります。不明状態とは検証に必要となる**検証情報が不足している状態**です。過去に<a href="http://eswg.jnsa.org/matsuri/201610/20161026-L4-miyachi.pdf">「電⼦署名検証を10分で説明してみる」</a>でも説明していますのでお時間があればご覧ください。

　さて検証に必要な情報には大きく分けると「**認証パスの証明書群** 以後、認証パス」「**各証明書の検証情報(CRL/OCSP等)** 以後、検証情報」に加えて「**署名時刻**」の3つがあります。細かく言えば他にもポリシー情報等がありますがここでは細かい話はしないでこの3つの情報について解説します。実はこれら検証情報の有無によって署名証明書が有効期限切れであっても「**有効/VALID**」と判定が出来ます。つまり**署名証明書の有効期限切れが署名の有効期限切れにはならない場合があります**。この辺りを今日は解説してみましょう。

　またPDF署名に関してはAdobe Readerの関係でまた別の状況があります。まず一般的な話をして、その後にPDF署名に関する署名の有効期限の話をします。

### ここまでのまとめ

:::note info
署名の検証結果には以下の3つの状態がある
|*検証結果*|*概要*|
|:-|:-|
|有効/VALID|必要な検証情報が揃っており署名が**有効**な状態。|
|不明/INDETERMINATE|必要な検証情報が揃っておらず署名が有効なのか無効なのか判別が出来ない**不明**な状態。|
|無効/INVALID|必要な検証情報が揃っているが失効や改ざんで署名が**無効**な状態。|
:::

:::note info
署名の検証に必要な主な情報として以下の3情報がある。
|*検証情報*|*概要*|
|:-|:-|
|認証パス|署名証明書からトラストアンカー（ルート証明書）までの証明書群。|
|検証情報|トラストアンカーを除く認証パス各証明書の検証情報（CRL/OCSP等）。|
|署名時刻|署名された時刻情報。システム時刻やRFC 3161のタイムスタンプ等。|
:::

# 署名検証の解説

### X.509電子証明書群（認証パス）

　PKIではトラストアンカーと呼ばれるルート証明書から利用者が使う署名証明書までの認証パスと呼ばれる証明書チェーンを使います。ルート証明書が署名証明書を直接発行していれば2階層となります。ルート証明書が中間CA証明書を発行し、中間CA証明書が署名証明書を発行する場合は3階層に、中間CA証明書が更に複数回発行されている場合には3階層以上になる場合もあります。署名証明書で署名された場合には**検証時に認証パスの全ての証明書が必要**となります。

　ところでX.509電子証明書には有効期限が設定されており無限に有効な証明書はありません。証明書には公開鍵暗号を利用しており、公開鍵暗号に限らず暗号方式はいずれ危殆化と呼ばれる状態になります。危殆化する理由は主に2つです。

1. 暗号を解くコンピューターの高速化（量子計算機も含む）
1. 暗号を解くアルゴリズムの進化（新しい解読手法等）

　つまり永遠に解かれない暗号方式は無いと言うことです。また鍵長を増やせば解くのが難しくなりますが、鍵長が増えると署名や検証のような場合にも計算時間がかかってしまい利便性が低下しますので使われる暗号方式は強度と利便性のバランスを見て決められており、強度が弱くなったら暗号方式の移行をおこないます。

　ありがたいことに<a href="https://www.cryptrec.go.jp/">CRYPTREC</a>等で安全な暗号方式の時期をまとめてくれています。過去例だとだいたい10～20年くらいで暗号移行が発生しています。実は次は2030年までに暗号移行することになっています。詳しくは<a href="https://qiita.com/lemiyachi/items/c20a18b172c6f192a262">「RSAの終わりの始まり - 暗号移行再び」</a>をご覧ください。

　証明書（公開鍵）とペアになった署名鍵の管理方法も有効期限に関係して来ます。ICカード等の専用ハードウェアの中に入っている署名鍵はどうやっても外部に取り出せないようになっています。しかしPKCS#12形式のファイルの中に入っている署名鍵は簡単にコピーが出来てしまうので、長い間使い続けていると漏洩する危険が増大して行きます。それを考えると短い期間で署名鍵を更新して行った方が安全と言う考え方があります。

:::note info
証明書の有効期限は何故あるか
以下の2つの理由で電子証明書には有効期限を設定することになる。

|*理由*|*説明*|
|:-|:-|
|暗号方式の危殆化|長く使っていると証明書に利用している暗号方式が解かれる可能性が高くなる。|
|署名鍵保持の安全性|長く使っていると署名鍵の管理方法によっては漏洩する可能性が高くなる。|

　この2つの理由により、一般の自然人に発行される証明書には、数ヵ月から最大5年程度の有効期限が設けられることが一般的です。ルート証明書の場合には、署名鍵をサーバー上のHSM（ハードウェア・セキュリティ・モジュール）で安全に管理し、一般向けより強い暗号方式を利用することで、10年以上の有効期限を持つ電子証明書が使われることはあります。しかしいずれにしても電子証明書には有効期限は設定されています。
:::

### 検証情報群（CRL/OCSP）

　証明書は色々な理由で失効する場合があります。例えばペアになる署名鍵の盗難等による漏洩時です。失効するとその証明書の有効期限前であってもその証明書は無効となります。検証確認とはその証明書が失効しているかどうかを確認すると言うことになります。確認方法はCRLかOCSPで行うことが一般的です。

<dl>
<dt>CRL(Certificate Revocation List) </dt>
<dd>証明書失効リスト。失効した証明書の一覧であり失効した日時と理由が記載されている。</dd>
<dt>OCSP(Online Certificate Status Protocol) </dt>
<dd>オンライン証明書ステータスプロトコル。証明書のステータスを返すプロトコル。オンライン問合せによりその証明書が有効か無効かのOCSPレスポンス情報を返す。</dd>
</dl>

　なおトラストアンカーであるルート証明書は無条件に信頼することになっているので通常は失効確認することはありません。

### 署名時刻

　署名時刻は署名付与した時間です。それは当たり前ですが実は検証時に一番重要な情報が署名時刻です。なぜなら**署名証明書は署名時刻に有効であれば良い**。と言うことになっているからです。つまり署名の有効性の確認は、署名値により非改ざんを確認し、署名証明書が署名時刻に有効であることで署名者を確認することになります。もし**信用される署名時刻が無い場合には署名証明書を検証時刻（現在時刻）に有効であるかどうかで検証する**ことになります。大事なことなのでまとめておきます。なおJNSAの「<a href="https://www.jnsa.org/result/e-signature/2021/">デジタル署名検証ガイドライン</a>」ではタイムスタンプの時刻を使うことになっており、署名時のシステム時刻であるSigningTime属性等は信用できないので利用しないことになっています。

:::note info
署名時刻の有無による検証方法の違い
|*署名時刻有無*|*検証方法概要*|
|:-|:-|
|署名時刻あり|署名証明書が<b>（信頼できる）署名時刻に有効</b>であることを確認。|
|署名時刻なし|署名証明書が<b>検証時刻（現在時刻）に有効</b>であることを確認。|
:::

　注意が必要な点として信頼できない署名時刻があると言うことがあります。信頼できない署名時刻とは後から改変可能であったり第三者が正しいと信用できない場合であったりと言うことになります。これに関しては検証ポリシー次第でありますが、詳しくは後述します。

　また検証に利用される検証情報もまた、署名時刻またはその後で発行された情報を使うことが望ましいです。

### 普通署名

　XML署名（XmlDsig）やJSON署名（JWS）等の署名フォーマットでは、署名ファイルの中に認証パスの証明書群を埋め込むことは可能ですし、署名時刻として署名を生成したシステムの時刻を埋め込むことも可能です。これが基本的な署名形式ですがここではこれを**普通署名**と呼びます。普通署名の検証では以下の手順で検証を行います。

<dl>
<dt>手順1.</dt><dd>認証パスを構築してトラストアンカーを確認する。</dd>
<dt>手順2.</dt><dd>各証明書の検証情報を認証局よりオンライン取得する。</dd>
<dt>手順3.</dt><dd>検証情報により各証明書が現在時刻で有効かどうか確認する。<br/>署名時刻が埋め込まれていたとしてもシステム時刻の場合には使わずに現在時刻で検証することが多い。</dd>
<dt>手順4.</dt><dd>以上全てが正常に完了した場合に署名は有効と認められる。</dd>
</dl>

　ではこの検証手順で署名証明書の有効期限後に検証するとどうなるでしょうか？まず現在時刻で検証を行った場合には有効期限が切れているので**無効/INVALIDと返す検証実装も多い**でしょう。ただし署名時刻が埋め込まれていて、その署名時刻を検証に利用する場合にはこの点は問題なしとなります。

|*問題*|*検証結果*|
|:-|:-|
|署名時刻が不明|タイムスタンプ等の信用できる署名時刻が無い為に現在時刻で検証するので期限切れの<b>無効/INVALID</b>となる。|
|検証情報が取得不可|認証局が有効期限切れの証明書に対して検証情報を提供しないケースでは<b>不明/INDETERMINATE</b>となる。|

　次に一般的に署名証明書を発行した認証局のポリシーでは有効期限切れの証明書に対して検証情報のCRLやOCSPを発行してくれない場合があります。そうすると手順2において検証情報が取れないことになります。この為に**検証情報が不足して不明/INDETERMINATEを返す実装が多い**でしょう。

　このことから普通署名はリアルタイムか短期間（署名証明書の有効期限まで）において使うべき仕様と言えます。普通署名である程度長期間の有効性を保持したいのであれば、有効期間の長い署名証明書を使う必要があると言うことになります。

### 長期署名（先進署名）

　普通署名では署名証明書の有効期限による制限がありますが、この問題を解決する方法が長期署名（先進署名）の仕様です。先の2つの問題に対して長期署名では以下の方法で解決します。

|*問題*|*検証結果*|
|:-|:-|
|署名時刻が不明|署名タイムスタンプ（RFC 3161仕様）を署名直後に取得し署名値に紐付けることで信用できる署名時刻を保証する。|
|検証情報が取得不可|署名証明書が有効な時（例えば署名直後）に取得しておいた検証情報を埋め込むことでオンライン取得しなくても良いようにする。|

　これを実現する長期署名の仕様がAdES-X-Longと呼ばれるものです。普通署名の部分はAdES-BESとなり、そこに署名タイムスタンプを追加してAdES-Tとなり、検証情報を埋め込んでAdES-X-Longとなります。このAdES-X-Longの仕様になっていれば、署名証明書の有効期限後であっても検証結果は**有効/VALID**となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/867320/5a963f10-691e-e220-1fad-8deb8206a47d.png)

　実は長期署名では上記2つの問題への対応だけではなく、アーカイブタイムスタンプを追加したAdES-Aにすることで、署名アルゴリズムの危殆化にも対応できると共に有効期間の延長にも対応できます。

|*問題*|*検証結果*|
|:-|:-|
|署名アルゴリズム危殆化|最新の危殆化していない署名アルゴリズムのアーカイブタイムスタンプ（RFC 3161仕様）を追加することで、署名と署名タイムスタンプの暗号アルゴリズムが危殆化しても有効性を維持出来る。|
|有効期間の延長|アーカイブタイムスタンプ（RFC 3161仕様）を追加することで、アーカイブタイムスタンプの署名証明書（TSA証明書）の有効期間まで延長することが出来る。|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/867320/09dfe9fc-ca83-c9c8-fc1f-c05a1c87063e.png)

　ですがここではアーカイブタイムスタンプについては詳しく説明しません。詳しくは<a href="https://qiita.com/lemiyachi/items/87d698e51e4a53c721d6">「Re:ゼロから始める長期署名」</a>を読んでください。

### ここまでのまとめ

:::note info
普通署名：署名証明書の有効期限切れ時の問題
|*問題*|*検証結果*|
|:-|:-|
|署名時刻が不明|現在時刻で検証するので期限切れの<b>無効/INVALID</b>となる。|
|検証情報が取得不可|認証局から検証情報が取得できないので<b>不明/INDETERMINATE</b>となる。|
:::

:::note info
長期署名：署名証明書の有効期限切れ時の対応
|*問題*|*検証結果*|
|:-|:-|
|署名時刻が不明|署名タイムスタンプにより信用できる署名時刻があるので<b>有効/VALID</b>となる。|
|検証情報が取得不可|証明書の有効期間内に認証局から検証情報を取得して埋め込むので<b>有効/VALID</b>となる。|
:::

　つまり普通署名の形式だと「**署名証明書の有効期限切れ＝署名の有効期限切れ**」となってしまうが、長期署名のAdES-X-Long形式であれば「**署名証明書の有効期限切れ≠署名の有効期限切れ**」であり署名証明書の有効期限切れであっても署名自体は有効とすることが出来ることになります。

# PDF署名検証の場合

　さてここまでは一般的な普通署名と長期署名の説明をして来ましたが、PDF署名の場合には少し事情が異なってきます。それは **Adobe Reader と言うデファクト標準の検証器がある**為です。Adobe Reader では署名証明書の有効期限は検証にどのように影響するのでしょうか。標準化された普通署名や長期署名と何が違うのでしょうか。次はそこを解説していきます。

### Adobe Reader の署名時刻（検証時刻設定）

　Adobe Reader のメニューから、[編集]-[環境設定] を実行すると「環境設定」画面が開きます。左にある分類タブから「署名」を選択して「検証」項目の「詳細ボタン」をクリックすると「**署名検証の環境設定**」が開きます。色々な設定項目がありますが左に「検証時刻」の設定があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/867320/4839ee12-7160-6ab0-e2ff-b5aa14a910f2.png)

　検証時刻の設定は以下の3つから選択します。デフォルト設定は最初にある「署名が作成された時刻」となります。

|*署名の検証に仕様する時刻*|*説明*|
|:-|:-|
|署名が作成された時刻|署名辞書の/Mキー値(署名日時)またはタイムスタンプ [デフォルト値]|
|署名に埋め込まれている保証された時刻(タイムスタンプ)|タイムスタンプがあれば利用するが署名辞書の/Mキー値は使わない|
|現在の時刻|検証する現在の時刻を利用して署名辞書の/Mキー値やタイムスタンプ委の時刻は使わない|

　さて皆さんはこんなマニアックな設定を変更することは無いと思いますので、通常 Adobe Reader を使ってPDF署名を検証するとデフォルト設定の「**署名が作成された時刻**」を使うことになります。署名タイムスタンプを使っていない場合には、署名辞書の/Mキー値と言う署名時に埋め込まれたシステム時刻を使います。/Mキー値は通常設定されているはずです。これにより検証時の署名時刻はタイムスタンプが無くても/Mキー値のシステム時刻を使うことになりますので過去の日時で検証することになります。これ**検証においてはとても重要なポイント**です。

### Adobe Reader の長期検証（LTV仕様）

　次に先の「署名検証の環境設定」にて「検証情報」のグループを見てみましょう。先の「検証時刻」グループの右にあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/867320/c44f00a0-5b68-c0e4-3687-73ddd7bce739.png)

　検証情報の設定は以下の3つから選択します。デフォルト設定は最初にある「検証情報が大きすぎる場合に確認」となります。なお埋め込みは検証が有効/VALIDの場合のみ可能となります。

|*署名済みPDFを保存時に自動的に検証情報を追加*|*説明*|
|:-|:-|
|検証情報が大きすぎる場合に確認|CRL等はデータサイズが大きいことがありますが、その場合に確認が表示される [デフォルト値]|
|常に|データサイズに関係なく常に検証情報をPDFに埋め込む|
|行わない|検証情報をPDFに埋め込まない|

　署名済みPDFファイルを Adobe Reader で開いてから保存すると検証情報が埋め込まれます。検証情報が埋め込まれるとどうなるのでしょうか？全ての検証情報が埋め込まれた署名は、Adobeの仕様としてLTV（Long-Term Validation：長期検証）と呼ばれる状態になります。Adobe Reader の署名パネルで確認することが出来ます。以下の例では左が検証情報埋め込み前で右が埋め込み後（LTV状態）です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/867320/448d466c-1092-da90-2e53-210c9c551a18.png)

　LTV状態になっていない場合には署名パネルに「署名はLTV対応ではなく、YYYY/MM/DD HH:MM:SS +09'00' を過ぎると有効期限が切れます」と表示されます。一方でLTV状態になっている場合には単純に「署名はLTV対応です」と表示されるだけで有効期限の表示がありません。これはどう言うことでしょう？

### Adobe Reader による署名の有効期限

 　検証時刻が「署名が作成された時刻」で、検証情報が「埋め込まれてLTV状態」になっているPDFファイルには有効期限がありません。大事なことなのでもう1回書きますね。**Adobe Readerで、検証時刻が「署名が作成された時刻」で、検証情報が「埋め込まれてLTV状態」になっているPDFファイルには有効期限がありません。**

:::note info
PDF署名のLTV対応時の有効期限
|*条件*|*検証結果*|
|:-|:-|
|検証時刻が「署名が作成された時刻」で、検証情報が「埋め込まれてLTV状態」|署名証明書の有効期限切れ後も<b>有効/VALID</b>となる。|
:::

　長期検証LTVの状態とは長期署名AdES-X-Longと同じでしょうか？いえ長期署名のAdES-X-Longでは署名タイムスタンプが必須ですが、長期検証LTVではシステム時刻を使った/Mキー値があれば良い点が異なります。**長期検証LTVはあくまでAdobe独自の検証仕様である**と言うことになります。

　タイムスタンプを要求しないので長期検証LTVの方が長期署名AdES-X-Longよりも手軽であるとは言えるでしょう。ただし標準仕様ではありません。これは色々な賛否や議論はあると思いますがここではふれません。

### PDF署名で証明書の有効期限切れを無くす方法

　最後にPDF署名で証明書の有効期限切れを無くす方法と言うか手順を説明します。Adobe Reader で利用可能な手順となります。

:::note info
Adobe Reader：LTV対応署名済みPDFファイルの作成手順
1. 「署名済みPDFを保存時に自動的に検証情報を追加」設定で「検証情報が大きすぎる場合に確認」または「常に」をセットする。設定変更していなければこの手順は不要です。
1. 署名を付与してから保存して、署名済みPDFファイルを作成する。普通署名である必要があり、MDP（証明）署名やロック署名にしていはいけません。
1. 保存した署名済みPDFファイルを再度読み込み検証を実行してから「名前を付けて保存」する。
1. 再度保存した署名済みPDFファイルを読み込み「LTV対応です」と表示されることを確認する。
:::

　つまり普通に署名して保存した後読み直し、検証してから再度保存すれば良いのです。簡単ですね。

# 大まとめ

### 署名証明書の有効期限切れ後に有効/VALIDにならないケース

:::note info
署名証明書の有効期限切れ後に有効/VALIDにならないケース
- 署名時刻が不明または信頼されていない
- 検証情報（CRL/OCSP）が無い
:::

　ただし署名証明書の有効期限が切れた場合に直ちに無効/INVALIDになるかと言うとそれも少し違います。署名時刻を何らかの方法で保証してやり検証情報を他から与えることができるのであれば有効/VALIDに出来るからです。その意味では普通署名であっても署名証明書の有効期限切れがそのまま無効になる訳で無く一定の信頼性はあると考えても良いでしょう。

### 署名証明書の有効期限切れ後に有効/VALIDになるケース

:::note info
署名証明書の有効期限切れ後に有効/VALIDになるケース
- 長期署名AdES-X-Long状態になっている（延長が必要）
- PDF署名で長期検証LTV状態になっている（延長も不要）

※ ただし暗号アルゴリズム危殆化があった場合を除く。
:::

　暗号アルゴリズムの危殆化にも対応する為にはアーカイブタイムスタンプの追加が必要です。また長期署名AdES-X-Longの場合も本来はアーカイブタイムスタンプを追加したAdES-Aにしておくことが望ましいです。厳密な長期署名はアーカイブタイムスタンプを追加して行く必要がありますがそれだけ信頼性は高いと言えます。
 
　PDFファイルに署名をするのであれば是非LTV状態に更新しましょう。それが良いかどうかは別にして、Adobe Reader では署名証明書の有効期限を気にする必要が無くなります。なおPDFファイルでも署名タイムスタンプを追加してPAdES-X-Longにすることは可能です。タイムスタンプが使えるのであれば署名時に署名タイムスタンプを追加しましょう。

### おわりに

　いかがだったでしょうか？これだけ長々と説明しないと署名証明書の有効期限切れ後の説明ができないのか！？そんなの普及する訳が無い！と言う人もいるでしょう。でも例えばPDFファイルに関しては署名後にもう一度読み込んで保存しなおすだけで良いのです。一般の利用者の皆さんがここに書かれたことを理解する必要はありません。Adobe Reader で検証結果が有効/VALIDになれば良いのです。でもエンジニアの皆さんは理屈を理解しておくとシステム設計時にどのような署名システムを作れば良いのか理解できるようになるのでお勧めです。PKIって難しいですが正しく使えば改ざん防止になります。検証も署名時刻としてシステム時刻を認めるかどうか等どこまで信用するかはポリシー次第と言えます。欧州ではサーバーで署名する場合にサーバーの運用規定があるのでシステム時刻も検証時刻として認めていたりします。あまり杓子定規に考えず何が必要なのかどういうリスクがあるのかを考えて自分に一番合った仕様やポリシーを選べば良いと考えています。こう書くとまたPKI技術者としては異端とかまた言われそうですw

### 参考情報

JNSA「<a href="https://www.jnsa.org/result/e-signature/2021/">デジタル署名検証ガイドライン</a>」
Qiita「<a href="https://qiita.com/lemiyachi/items/87d698e51e4a53c721d6">Re:ゼロから始める長期署名</a>」
JNSA ESWG (PDF)「<a href="http://eswg.jnsa.org/matsuri/201610/20161026-L4-miyachi.pdf">電⼦署名検証を10分で説明してみる</a>」
LangEdge (PDF) 「<a href="https://www.langedge.jp/download/jnsa/20131030-SUTF-4-pdfsign.pdf">なんとなく分かった気になるPDF電子署名仕様入門2</a>」