はじめに
これまで、iOS / Android/ Windows / macOS / ChromeOS / Linux のそれぞれの OS において、実際にルート認証局(CA)証明書を証明書ストアに登録し、動作確認を行ってきました。
結果、証明書ストアと一言で言っても、OS により管理方法が異なるうえに、OS が管理しているものやアプリケーションが管理しているものといったように、複数の証明書ストアが存在することがわかりました。また、どうやら証明書ストアには、ルート認証局(CA)証明書以外のものも格納されているようです。
このように、証明書ストアというものが単一のものではなく、複数のものの総称であるという点が、証明書ストアの理解を難しくしています。
そこで、今回は、いままで実践で確認してきたことを基準に、証明書ストアについて少し読み解いていきたいと思います。
※ なお、この内容は、記事作成時点で筆者の環境にて確認したものをベースにしております。そのため、環境による違いや、今後のOS やブラウザの変更により、変わる可能性がある点をご理解お願いします。
証明書ストアとは
証明書ストアとは、一般的に証明書やその証明書に対する信頼情報などを管理する仕組みのことを言います。
その実態は、簡単に言えば 「信頼できる相手のリスト」 です。
そして、信頼できる相手として、「信頼する CA の一覧」を保存している場所が 証明書ストア(Certificate Store) になります。
歴史的に、証明書ストアは、SSL/TLS と HTTPS の誕生(1990年代)とともに必要になった仕組みです。Windows 2000 が OS 機能として正式に導入したことで、現在につながる OS レベルの証明書管理の形が確立しました。ただし、その前身となる「信頼できる鍵の集合」という仕組みは 1980 年代の企業ソフトにも存在していました。
| 年代 | 事柄 |
|---|---|
| 1980年代 | 公開鍵暗号と X.509 が誕生(証明書の基礎) |
| 1990年代前半 | SSL が登場 → ブラウザが CA を持ち始める |
| 1999年 | Windows 2000 が OS レベルの証明書管理機能を強化・整備 |
| 2000年代 | TLS と HTTPS の普及 → 証明書ストアが一般化 |
| 2010年代 | Let's Encrypt 登場 → 証明書の自動化が進む |
| 2020年代 | ローカル開発用 CA(mkcert)が一般化 |
証明書ストアはもともと「信頼できる認証局(CA)の一覧」を管理するために生まれた仕組みで、HTTPS の普及とともに 1990年代後半に確立しています。
証明書ストアという言葉が指すものは、まずはこれが基本となります。
その後、コード署名やクライアント認証の普及により、証明書ストアは「信頼ストア」と「キーストア」を兼ねる総合的な証明書管理システムへと進化していきました。
つまり、現時点で証明書ストアと言った場合、「信頼できる認証局(CA)の一覧」を管理する「信頼ストア」だけでなく、コード署名やクライアント認証などの「キーストア」も含むものとなります。
クライアントとサーバーとで異なる証明書ストア
証明書ストアが指し示すものは、クライアントとサーバーでも異なります。
ここでいう、クライアントとサーバーは、物理的な筐体の分類ではなく、機能の違いを示しています。
- クライアント: Web ブラウザや curl, wget コマンドなど、Web サーバーに要求を出す機能
- サーバー: Web サーバーなど、クライアントからの要求により応答を返す機能
┌────────────────┐ ┌────────────────┐
│ クライアント │ │ サーバー │
│ │ │ │
│ Web ブラウザ ──── HTTPS 要求 ───▶ Web サーバー │
│ △ │ │ │ │
│ │ │ │ │ │
│ └─────────── HTTPS 応答 ───────────┘ │
│ │ │ │
│ │ │ │
└────────────────┘ └────────────────┘
👉 パソコンやサーバーなどの1つの筐体の中には、このクライアント機能とサーバー機能の両方を同居させることが可能です。
■ クライアントでの証明書ストア
クライアントでの証明書ストアでは、信頼する認証局(CA)の証明書や、コード署名、クライアント認証のための証明書やキーなどを保管しています。
例:
- Windows:信頼されたルート証明機関
- macOS:System Roots
- Linux:/etc/ssl/certs/ca-certificates.crt
- Firefox:NSS
- Chrome(Linux):NSS
💡 近年のChromeにおける進化(Chrome Root Store):
以前の Chrome では、証明書の信頼判定に OS が提供する仕組みを利用する部分が大きく、OS によって挙動が異なっていました。しかし近年では、 OS が提供する証明書ストアの参照に加え、「Chrome Root Store(Certificate Management V2)」と呼ばれる、Chrome 独自のルート証明書管理の仕組みも導入されています。
■ サーバーでの証明書ストア
サーバーでの証明書ストアでは、TLS を提供するために、
- 自分自身の秘密鍵(private key)
- 自分自身のサーバー証明書(public key)
- 中間 CA(チェーン証明書)
を持ちます。
これらは OS の証明書ストアではなく、Web サーバーやアプリケーションが独自に持つ秘密鍵の保管領域に保存されます。
例:
- Apache:server.crt / server.key
- Nginx:ssl_certificate / ssl_certificate_key
- IIS:秘密鍵付き証明書ストア(CryptoAPI)
- Java:JKS / PKCS#12
- Node.js:ファイルパスで直接読み込む
💡 ワンポイント:
サーバーの秘密鍵は、絶対に外部へ公開してはいけない最重要情報です。クライアント(ブラウザ)に登録するのは、あくまで認証局の「パブリックなCA証明書(公開鍵)」であり、サーバーの秘密鍵ではありません。ここを混同して秘密鍵を配ろうとしてしまうトラブルも多いため注意しましょう。
このように、クライアントとサーバーにおいて、証明書ストアという言葉が示すものは、全く別物であるという点には、注意が必要です。
前述のとおり、1筐体の中に、クライアントとサーバーは共存が可能です。この場合、証明書ストアと呼ばれる2種類の存在が共存することになるため、分けて認識することが重要です。
| 機能 | ストアの種類 | 何が入る? |
|---|---|---|
| クライアント | 信頼ストア、キーストア | 認証局(CA)の一覧、コード署名やクライアント認証のための証明書 |
| サーバー | 秘密鍵ストア | サーバー証明書+秘密鍵 |
過去記事の「開発環境について/HTTPSテスト環境について」で扱った mkcert コマンドで作成したサーバー証明書を保管したところが、ある意味サーバーの証明書ストアになります。通常の HTTPS サーバーでは、これらの証明書や秘密鍵を、ファイルや OS 、アプリケーションなどの仕組みを利用して管理しています。
一方、前回までの HTTPS テスト環境にアクセスするために登録してきた証明書ストアは、クライアントの証明書ストアを示します。
まず、この違いを分けて認識することが大切です。
次章以降では、このクライアントでの証明書ストアについてもう少し詳しくみていきたいと思います。
※ 以降、証明書ストアとは、クライアントでの証明書ストアを指すものとします。
※ 証明書ストアには、「信頼できる相手のリスト」 だけでなく、コード署名やクライアント認証のための証明書なども保管されています。コード署名やクライアント認証も Web を構成する重要な技術ですが、これらに対する説明は別の機会とし、本記事では、HTTPS サーバーへの接続で利用される「信頼できる相手のリスト」だけに着目して、説明を行います。
なぜ証明書ストアが必要なのか
証明書ストアが必要な理由は、インターネットでの通信を安心・安全に行うためです。
HTTPS や TLS の世界では、通信相手の証明書が重要です。その証明書が本物かどうかを判断するために、証明書を発行した「どの認証局(CA)を信頼するか」を OS やブラウザが知っている必要があります。
その際に、利用されるのが、証明書ストアです。
通信相手から送られてきた証明書の発行もと(認証局(CA))をこの証明書ストアで確認することにより、該当する証明書を信頼がおけるものかどうかを確認することができます。
OS や アプリケーションによる証明書ストアの違い
では、この証明書ストアとは、1つのものを指しているのでしょうか?
前述のとおり、証明書ストアは、Web の発展により追加された機能であるため、OS の歴史からみれば比較的新しい機能になります。
当然のことながら、OS によってもその実装は様々です。Linux などでは、ユーザーランドの違いにより、ディストリビューションによっても様々です。
そして、ここが混乱を巻き起こす点ですが、OS の内部でも1つに統一されていないということです。
実は、証明書を利用するアプリケーション(ブラウザ)によっても、独自のストアを有しているものもあり、1つの OS の中であっても、OS が管理するもの、アプリケーションが管理するものといったように、複数の証明書ストアが存在しています。
例:
| OS | 代表的な管理場所・仕組み | 設定方法 |
|---|---|---|
| iOS | プロファイル | OSの設定 |
| Android | OS システム/ユーザー暗号化ストア | OSの設定 |
| Windows | Windows Certificate Store | OSの証明書マネージャ |
| macOS | キーチェーン | securityコマンドかキーチェーンアクセス |
| ChromeOS | Chrome Root Store / ローカル証明書など | Chromeブラウザの証明書マネージャ |
| Linux(Debian 系) | /usr/local/share/ca-certificates/ | update-ca-certificatesコマンド |
| Linux(Red Hat 系) | /etc/pki/ca-trust/ | update-ca-trust extractコマンド |
| Linux(Arch 系) | /etc/ca-certificates/trust-source/ | trust / update-ca-trustコマンド |
| Linux(Alpine 系) | /usr/local/share/ca-certificates/ | update-ca-certificatesコマンド |
| Linux(ブラウザ用) | ~/.local/share/pki/nssdb/ もしくは ~/.pki/nssdb/ | certutilコマンド |
※ Linux の場合、筆者の環境では、Linux(Debian系)の証明書ストアではなく、Linux(ブラウザ用)の証明書ストアに登録する必要がありました。また、証明書ストアとして、~/.local/share/pki/nssdb/ ではなく、~/.pki/nssdb/ が使われていました。
さらに、アプリケーションによっては、 OS の証明書ストアを使わないものもあります。
- Java → cacerts(独自)
- Firefox / Thunderbird → NSS DB(独自)
- Python → certifi(独自)
- Node.js → Mozilla CA バンドル(独自)※デフォルト動作
- Docker コンテナ → イメージ内の CA(独自)
これらの証明書ストアは、仕掛けや保管場所も異なります。また設定方法も様々です。
つまり、クライアントでの証明書ストアとサーバーでの証明書ストアを全く別物として分類しましたが、実は、クライアントでの証明書ストアも1つのものではなく、別々に管理された複数の証明書ストアを示す総称となっています。
証明書ストア
│
├─ クライアントでの証明書ストア
│ │
│ ├─ OSで管理する証明書ストア
│ │
│ └─ アプリケーション毎に管理される証明書ストア
│
└─ サーバーでの証明書ストア
このように、証明書ストアと一括りにされていることが、混乱を引き起こし、その理解を難しくする要因の1つです。
この点を理解していないとルート認証局(CA)証明書を証明書ストアに登録したにも関わらず、認識されないというトラブルに巻き込まれる確率が高くなります。
OS が管理する証明書ストア
OS が管理する証明書ストアは、OS が提供・管理する証明書管理の仕組みです。前回までの実践で、ルート認証局(CA)証明書の登録を行ってきたのが、この OS が管理する証明書ストアになります。
※ Linux に関しては、OS統一のGUIストアが存在しない(またはアプリが各自で持つ文化がある)ため、OS の各種コマンドが参照する証明書ストアとブラウザが参照する証明書ストアが別物として分かれて存在しています。過去記事、「開発環境について/Linux端末でのルート認証局(CA)の証明書設定実践」では、ブラウザが参照する証明書ストア(Linux(ブラウザ用))にルート認証局(CA)証明書を登録して、動作確認を行っています。
これらは、OSやディストリビューションによって違いはありますが、それぞれ証明書ストアを管理するためのGUIやコマンドが用意されています。
この OS が管理する証明書ストアは、利用するアプリケーションも多く存在します。
そのため、複数のアプリケーションから共通して利用したい場合には、OSが管理する証明書ストアへの登録が有効です。
ただし、下記に示すような欠点があります。
- テストで使用したいだけであるにもかかわらず、OS の証明書ストアを汚してしまい、テスト完了後の消し忘れなどによる脆弱性を引き起こす可能性がある。
- OS ごとに実装方法や操作方法が異なるため、それに合わせた対応が必要になる。
- 本来、ブラウザでの HTTPS だけに使用したいだけにもかかわらず、wget や curl といったその他のアプリケーションにまで許可範囲を広げすぎてしまう。
- Linux の場合、ブラウザが参照する証明書ストア(Linux(ブラウザ用))の存在箇所が、 ~/.pki/nssdb/ から ~/.local/share/pki/nssdb/ に変更された経緯などもあり、使用している環境で、どちらが利用されているかを確認する必要がある。
- Linux 版 Firefox は、標準状態では Windows 版や macOS 版のように、OSが管理する証明書ストアを自動的に参照しない。
👉 これらの点を十分認識したうえで、登録を行うことが重要です。特に Linux の場合は、使用している証明書ストアのパスが違ったり、ブラウザとして Firefox を利用していると登録したはずなのに、反映されないといったトラブルに直結します。
※ Linux では、p11-kit などを利用してシステムの証明書を Firefox から利用できるようにする方法があります。また、Linux ディストリビューションによっては、 Firefox と OS が管理する証明書ストアを統合するための独自の対応が行われているものもあります。
ブラウザが利用する証明書ストア
Safari やモバイル OS 上のブラウザでは、 OS が管理する証明書ストアを利用する構成が一般的です。
その他多くのブラウザは、独自の証明書ストアを内包しています。ただし、その場合であっても、完全に独自の証明書ストアしかみていないかというとそうではありません。
ブラウザによっては、独自の証明書ストアだけでなく、OS が管理する証明書ストアを参照する構成もあります。
※ ただし、Linux 版の Firefox に関しては、標準では OS が管理する証明書ストアを参照しないため、後述の独自の証明書ストアのカスタムを利用する必要があります。( ただし、ディストリビューションによっては、 Firefox と OS が管理する証明書ストアを統合するための独自の対応が行われているものもあります。)
この機能のおかげで、OS が管理する証明書ストアに、ルート認証局(CA)証明書を登録しても警告表示がでないアクセスを行うことができます。
また、この独自の証明書ストアには、カスタムでルート認証局(CA)証明書を登録することも可能です。この機能は、ブラウザの設定画面からたどれる証明書マネージャにより提供されています。
当然のことながら、独自の証明書ストアに格納されるため、OS が管理する証明書ストアとは別物です。OS が管理する証明書ストアに書き込まれることもありません。
※ ここでいう「別物」とは、管理主体と利用範囲が異なるという意味です。内部でどのような形式・場所に保存されているかについては、OSやブラウザの実装によって異なります。
つまり、カスタムで登録したルート認証局(CA)証明書は、登録先のブラウザが管理する証明書ストアで利用され、OSが管理する証明書ストアには影響しません。
また、この設定方法では、同一ブラウザであれば、OS の垣根を越えて操作手順も統一化されており、ユーザーがその実装の違いを知る必要はありません。また、Linux の場合のようにディストリビューションの違いや、OS コマンドとの保管場所の違いといったことを意識する必要もありません。
証明書の有効範囲を該当ブラウザに限定できることや、テストが完了すれば、ブラウザから外すだけで済むため、テスト環境が抱えるリスクを抑えることも可能です。
欠点としては、
- OS や他のアプリケーションからは、登録したルート認証局(CA)証明書を認識されない。
- 使用するブラウザの種類毎(Chrome/Chromium/Firefox/Edge/Operaなど)にルート認証局(CA)証明書の登録が必要である。
というぐらいです。
この点を踏まえると、HTTPS テスト環境に接続するだけといった限定的な用途では、ルート認証局(CA)証明書の登録先として適した方法の一つといえます。
次回予告
次回は、Chrome ブラウザを例にとり、ブラウザにおける証明書ストアの管理について、もう少しみていきたいと思います。