公開鍵があれば電子署名を検証できます。でも、受け取った公開鍵が本当に署名者のものかは、公開鍵だけを見てもわかりません。
誰かが自分の公開鍵を「Aさんの鍵です」と渡してきたら、どう見分けるのでしょうか。そこで使うのが電子証明書です。この記事では、架空の認証局と署名者を登場させ、証明書の発行からPDFの検証までを数字で追います。
鍵は2組ある
AさんがPDFに署名し、認証局がAさんの公開鍵を証明する場面を考えます。
| 持ち主 | 秘密鍵の用途 | 公開鍵の用途 |
|---|---|---|
| Aさん | PDFに署名する | PDFの署名を検証する |
| 認証局 | Aさんの証明書に署名する | 証明書の署名を検証する |
認証局が署名する対象は、PDFではなくAさんの証明書の内容です。
認証局の秘密鍵 ──署名──> Aさんの証明書
Aさんの秘密鍵 ──署名──> PDF
証明書の中身
電子証明書を簡略化すると、次の形です。
Aさんの証明書
┌──────────────────────────┐
│ 名前:Aさん │
│ 公開鍵:Aさんの公開鍵 │
│ 発行者:認証局 │
│ 有効期間など │
├──────────────────────────┤
│ 上記の内容に対する │
│ 認証局の電子署名 │
└──────────────────────────┘
名前と公開鍵が一緒に入っており、その組み合わせに認証局が署名しています。証明書の内容は暗号化されて隠されるわけではありません。Aさんの秘密鍵も入っていません。
認証局の署名が正しいと検証できれば、「認証局がこの名前と公開鍵の組み合わせに署名した」と確認できます。現実の本人と鍵の結びつきについては、認証局が適切に本人確認したことも前提になります。
数字を使って証明書を作る
以下は仕組みを追うための架空の教材です。小さすぎる鍵と仮のハッシュ値を使い、実際に必要な署名用の処理を省いています。この方法を実用しないでください。
認証局の鍵を、次のように決めます。
認証局の公開鍵: (187, 7)
認証局の秘密鍵: (187, 23)
この例の署名と検証には「割った余り」を使います。17 mod 5 = 2 は、17を5で割った余りが2という意味です。
署名: 値の23乗を、187で割った余り
検証: 署名の7乗を、187で割った余り
Aさんの証明書に入れる情報は次の通りです。
名前:Aさん
公開鍵:(143, 7)
発行者:認証局
この情報をハッシュした結果が、説明のために 2 だったと仮定します。実際のハッシュはずっと大きな値です。
認証局は秘密鍵の 23 を使って署名します。
2²³ mod 187 = 162
すると、証明書には情報と署名 162 が入ります。
Aさんの証明書
├─ 名前:Aさん
├─ Aさんの公開鍵:(143, 7)
├─ 発行者:認証局
└─ 認証局の署名:162
ここで使ったのは認証局の秘密鍵です。Aさんの秘密鍵を認証局に渡して署名してもらう必要はありません。
受け取った証明書を検証する
検証者は、認証局の公開鍵 (187, 7) をあらかじめ信頼するものとして持っているとします。この鍵を使って、証明書の署名 162 を検証します。
162⁷ mod 187 = 2
同時に、受け取った証明書の情報からハッシュ値を計算します。こちらも 2 です。
証明書の情報から計算した値:2
認証局の署名を検証した値 :2
───
一致
この計算は手元でできます。検証するたびに認証局のデータベースへ「同じ証明書がありますか」と問い合わせる必要はありません。
公開鍵を書き換えられたら
攻撃者が、証明書のAさんの公開鍵を自分のものに書き換えたとします。変更後の情報のハッシュが 3 になったと仮定すると、検証結果はこうなります。
変更後の証明書の情報から計算:3
元の署名162を検証した結果 :2
───
不一致
コピーされた署名 162 は、元の情報に対するものです。変更後の内容に合う認証局の署名を新たに作るには、認証局の秘密鍵が必要になります。
ただし、この教材では 187 = 11 × 17 と簡単に分解できるため、秘密鍵も簡単に求められます。実際に安全な仕組みでは、十分に大きな鍵と適切な署名方式を使います。また、実際のハッシュは異なる入力が同じ結果になる可能性をゼロにはできませんが、それを悪用することが困難になるように選ばれています。
PDFの署名は別に検証する
証明書の検証が終わったら、そこからAさんの公開鍵 (143, 7) を取り出します。PDFの署名を検証するためです。
Aさんの鍵ペアを、教材用に次のようにします。
Aさんの公開鍵:(143, 7)
Aさんの秘密鍵:(143, 43)
PDFの署名対象をハッシュした結果が 4 だったと仮定します。Aさんは自分の秘密鍵を使います。
署名:4⁴³ mod 143 = 108
受け取った人は、PDFから計算した値 4 と、Aさんの公開鍵を使った検証結果を比べます。
検証:108⁷ mod 143 = 4
PDFから計算した値:4
署名を検証した値 :4
───
一致
証明書の検証とPDFの検証は、使う公開鍵が違います。
信頼済みの認証局の公開鍵
│
└─ 認証局による「Aさんの証明書」への署名を検証
│
▼
Aさんの公開鍵を取り出す
│
└─ Aさんによる「PDF」への署名を検証
認証局の公開鍵はどこから信頼する?
ここまでの計算では、認証局の公開鍵を「あらかじめ信頼している」と置きました。これは省略できない前提です。
攻撃者が自分の公開鍵を「認証局の公開鍵」と名乗って渡すこともできます。その鍵をそのまま信頼すれば、攻撃者が作った証明書を正しいと判定してしまいます。
そこで、検証ソフトやサービスは、信頼できる経路で認証局の証明書や公開鍵を入手し、信頼の起点として設定します。これがトラストアンカーです。中間の認証局がある構成では、署名者の証明書から中間認証局の証明書をたどり、最終的に信頼の起点に到達するかを確認します。これが証明書チェーンです。
認証局の自己署名証明書には、その認証局自身の公開鍵と署名が入っています。ただし、自己署名が検証できるだけでは発行者が本物かはわかりません。攻撃者も自分の鍵で自己署名証明書を作れるからです。
マイナンバーカードでは
公的個人認証サービスでは、J-LISの署名用認証局が署名用電子証明書を発行します。カード内には署名用の秘密鍵と証明書があり、証明書には利用者の公開鍵などが含まれます。秘密鍵はカード外から読み出せない設計です。
J-LISの署名用認証局の自己署名証明書は、公的個人認証サービスポータルで公開されています。JPKIの検証方式については、デジタル庁の民間事業者向けガイドラインに説明があります。
カードで文書に署名するたびに、J-LISが文書に署名し直すわけではありません。文書への署名には、カード内の利用者の秘密鍵を使います。なお、実際に使うアプリや電子契約サービスによって、文書をサービスへ送信するか、署名データをどこで管理するかは異なります。
証明書の署名の計算と、証明書が失効していないかの確認も別です。署名が数学的に正しくても、カードの紛失などにより証明書が失効している場合があります。オフラインで署名の計算が成功しただけでは、最新の失効状態まで確認できたとは限りません。
実際のRSA署名との違い
この記事の計算は、RSAの関係をつかむための単純化です。実際の署名では、ハッシュした値をそのままべき乗するのではなく、署名方式が定める符号化などの処理を行います。暗号化と署名も、目的と手順が異なります。詳しくはRFC 8017を参照してください。
証明書がつないでいるのは「名前などの情報」と「公開鍵」です。その結びつきを認証局の署名で検証し、さらにその公開鍵でPDFの署名を検証する。2つの署名を別々に追うと、証明書の役割が見えてきます。