オブジェクトの広場はオージス総研グループのエンジニアによる技術発表サイトです

組み込み/セキュリティ

デジタル証明書を使った設計

オージス総研 組み込みソリューション部
小野 峰和
2021年12月21日

デジタル証明書(電子証明書)を間違った方法で使ってしまうと、過剰な運用コストがかかることや、情報資産を保護できず被害を受けるリスクが高くなることもあります。本記事ではデジタル証明書を使った設計を行う際のポイントについて例を挙げてご紹介します。

はじめに

セキュリティ対策としてデジタル証明書(または、電子証明書とも呼ぶ)を使うケースが多くなってきています。 例えば、ブラウザからWebページにアクセスする時や、VPNの認証などで利用しています。 しかし、利用者はこのデジタル証明書を扱うケースは意外と少ないのではないでしょうか?

セキュリティ機能でデジタル証明書を使用するどうすれば良いのでしょうか。そもそもデジタル証明書がどのようなものなのか、なぜ必要なのか分からない人も多いでしょう。 セキュリティ機能の開発経験のある人でないとイメージしにくいのではないでしょうか?

デジタル証明書は暗号鍵の運用に関わるセキュリティ対策手段の一つです。

デジタル証明書の課題

今回は、デジタル証明書の概要と設計を行う際のポイントについて、例を挙げてご紹介します。

デジタル証明書はなぜ必要?

はじめに、デジタル証明書はなぜ必要なのかについて説明します。

デジタル証明書は公開鍵暗号方式を利用する際に用います。 公開鍵暗号方式とはプライベート鍵と公開鍵(パブリック鍵とも呼ぶ)の鍵ペアを使う暗号方式のことです。 例として、RSA鍵やECC鍵などがあります。この公開鍵暗号方式は、主に次の2つの用途で使用されます。

  • データの暗号化(盗聴防止)
  • データの検証(改ざん防止)

「データの暗号化」では、公開鍵を使って機密データを暗号化し、プライベート鍵を使って機密データを復号します。具体的な例として、通信暗号用の使い捨てのセッション鍵を通信相手と共有するために使用します。

公開鍵を使った暗号

「データの検証」では、プライベート鍵を使って対象データに検証値を生成し、公開鍵と検証値と対象データを使って対象データの正当性を確認します。この検証値のことを署名、正当性を確認することを署名検証とも呼びます。

公開鍵を使った検証

この2つのどちらの用途においても、最初に相手に公開鍵を送る必要があります。

この公開鍵は、「公開」という名称からもわかるとおり、第三者に見られても問題ありません。 そのため、公開鍵を相手にそのまま渡せばよいのですが、実際の運用では、デジタル証明書として渡す手段が多く利用されています。デジタル証明書は「公開鍵証明書」とも呼ばれます。では、なぜわざわざデジタル証明書を使うのでしょうか?

デジタル証明書の利用目的は主に以下の2つです。

  • 公開鍵の利用者に鍵の利用方法を伝える【情報共有】
  • 公開鍵の利用者が正しい鍵であることを検証できるようにする【改ざん防止】

この2つの利用目的について詳しく説明します。

デジタル証明書の利用目的(1) 情報共有

はじめに、「公開鍵の利用者に鍵の利用方法を伝える」情報共有について説明します。

公開鍵には鍵情報しか含まれていません。利用者はこの公開鍵の利用方法が必要になります。 しかしその情報を別の手段で渡してしまうと、その利用情報を誤って使ってしまうかもしれません。 そこで、デジタル証明書では、公開鍵と一緒に鍵の利用方法を記載します。

情報共有

例えば、以下の公開鍵の利用情報が一般的なデジタル証明書に含まれています。

  • 証明書を発行した人(発行者,Issuer)
  • 証明書を発行依頼した人(サブジェクト,Subject)
  • 証明書の有効期限
  • 公開鍵の仕様(暗号アルゴリズム)
  • 公開鍵の利用用途(署名生成、暗号化、鍵共有など)

ウェブブラウザでサイトにアクセスした後、URLの近くの鍵マークをクリックすると、サーバ証明書が表示できますので、一度見てみてください。デジタル証明書に、どのような内容が書かれているかの具体的なイメージができるはずです。

サーバ証明書サンプル

では、このデジタル証明書に含まれている関連情報を使うメリットを説明します。

共通仕様がある

デジタル証明書は、X.509証明書として世界共通のフォーマットが決まっています。(参照 RFC5280)

このフォーマットに準拠した証明書を作成することで、だれでも公開鍵に関する情報を理解することができます。 さらに設計観点でいえば、共通仕様であることから、デジタル証明書を処理できる汎用ソフトウェアを使って機能実装することができます。もし暗号鍵の仕様変更があっても、証明書仕様に準拠していれば、容易にサポート対応できます。

有効期限を指定できる

暗号鍵には解読リスクや漏洩リスクがあるため、有効期限(寿命)を設定し定期的に鍵を更新するセキュリティ対策を行うことが多くあります。 デジタル証明書を利用すれば、有効期間外では鍵を使えないようにすることができます。

有効期限内でも失効できる

有効期限内でも、鍵が漏洩してしまった場合は鍵を使用しないように利用者に通知する必要があります。 失効したことを通知するための証明書失効リスト(CRL:Certificate Revocation List)がX.509仕様で定められています。 デジタル証明書を利用すれば、失効した鍵を使えないようにすることができます。

デジタル証明書の利用目的(2) 改ざん防止

次に、利用者が正しい鍵であることを検証できるようにする、改ざん防止について説明します。

鍵の関連情報と公開鍵を相手に送っただけだと、受け取った相手は送られてきた情報が本当に正しいかを確かめることができません。そこで、検証値も一緒に送って確認できるようにします。 デジタル証明書では、公開鍵と鍵の関連情報と検証値が含まれています。

image-20211004094451929

しかし、このデジタル証明書の送付にはまだ課題が残っています。 それは「検証値を使って確認するためには検証鍵が必要」ということです。

デジタル証明書には検証値がついていますが、その検証を行うための検証鍵はデジタル証明書には付与されていません。検証鍵を何らかの手段で相手に渡す必要があります。

デジタル証明書で送付する鍵とは別の検証鍵を使う場合

そこで、送付する公開鍵とは別の検証鍵を用意することにします。 信頼できる第三者が検証鍵を管理してデジタル証明書の検証値を作ることにします。

image-20211004102817176

上の図では、信頼できる第三者の信夫さんに検証鍵を管理してもらう例を示しています。

太郎さんは信夫さんに自分の公開鍵の検証値を作ってもらいます。そして作成してもらった検証値をデジタル証明書内に付与します。そのときに検証者である信夫さんを発行者としてデジタル証明書に記載します。

公開鍵を受け取る側の花子さんは、太郎さんからデジタル証明書を受け取ったら、発行者の項目を確認します。「信夫」さんが発行者になっているので、別の手段で入手した信夫さんのデジタル証明書に含まれている公開鍵を使って、太郎さんのデジタル証明書を検証します。

このようなデジタル証明書を検証するための証明書のことをCA(Certification Authority : 認証局)証明書と呼びます。

デジタル証明書で送付する鍵と検証鍵が同じ場合

なぜ公開鍵を渡すために別の検証鍵を使わなければならないのか、同じ鍵でもいいのでは?と思うかもしれません。

では送付する鍵と検証鍵が同じ場合を考えてみましょう。

image-20211004100700631

図のように、太郎さんが作成したデジタル証明書を悪夫さんが悪用しようとしているとします。太郎さんのデジタル証明書の鍵情報を複製し、悪夫さんが持っている別の鍵で検証値を作ったデジタル証明書を作成します。

このデジタル証明書を受け取った花子さんは、デジタル証明書に含まれている鍵情報を見て、太郎さんが作成したものと勘違いします。そして検証鍵も送付してきた鍵を使うので、検証は成功します。花子さんは、悪夫さんが作った証明書の公開鍵を、太郎さんが作成したものだと信じてしまいます。

このように、送付する鍵と検証鍵を同じにしてしまうと、第三者が不正な別の証明書を作成して、悪用できてしまいます。

デジタル証明書に含まれている鍵と検証鍵が同じ証明書を自己署名証明書と呼びます。この自己署名証明書は簡単に成りすますことが可能なので、俗称として「オレオレ証明書」と呼ばれることもあります。この自己署名証明書はセキュアな環境で受け渡しを行い、改ざんされないように管理する必要があります。

複数のデジタル証明書を使って検証する場合

今までの例では2つの証明書の説明でしたが、3つ以上の証明書を使うケースもあります。

3つ以上の証明書を使う場合でも、目的は変わりません。複数の証明書を扱う場合でも、あるひとつの証明書に含まれている公開鍵の正当性を確認するために使用します。

では、図の例を使って証明書の発行方法について説明します。

  • 太郎さんの公開鍵を証明するために、中川さんのプライベート鍵を使って、太郎さんの公開鍵のデジタル証明書を発行します。
  • 中川さんの公開鍵を証明するために、山中さんのプライベート鍵を使って、中川さんの公開鍵のデジタル証明書を発行します。
  • 山中さんの公開鍵を証明するために、信夫さんのプライベート鍵を使って、山中さんの公開鍵のデジタル証明書を発行します。
  • 信夫さんの公開鍵を証明するために、信夫さん自身のプライベート鍵を使って、自己署名証明書を発行します。

image-20211004111218413

プライベート鍵を他人に渡すことはありません。検証値があっていれば、それはそのプライベート鍵の所有者が証明書を発行した=公開鍵を正しいものと証明したことになります。

この図のような証明書を発行した場合、以下のことと同じ意味になります。

  • 太郎さんの鍵は中川さんが証明している
  • 中川さんの鍵は山中さんが証明している
  • 山中さんの鍵は信夫さんが証明している
  • 信夫さんの鍵は信夫さん自身が証明している

この信夫さんの証明書のように、複数の証明書を使った場合においても、信頼できる自己署名証明書を1つ必ず作成して使用することになります。この証明書をルート証明書とよびます。

このルート証明書は自己署名証明書なので、前述の通り証明書を改ざんできてしまいます。信頼の起点:トラストアンカーと呼ばれることもあり、改ざんされないように更新不可の状態で管理することが重要となります。

そして、山中さんと中川さんの証明書のように、ルート証明書を除いた証明書を検証するための証明書を中間CA証明書と呼びます。

太郎さんの証明書のように、相手に渡したい公開鍵が含まれている証明書をリーフ証明書と呼びます。木に例えて、ルート=根とリーフ=葉という表現になっています。

ルート証明書、中間CA証明書、リーフ証明書の証明書群のことを証明書チェーンと呼びます。これらすべての証明書が鎖のようにつながっており、すべて検証確認できれば、リーフ証明書に含まれている公開鍵の正当性を証明できます。

では、利用者が実施する証明書の検証方法について説明します。

image-20211004113912449

太郎さんの鍵が正しいことを検証するために証明書群を受け取った花子さんは、以下の項目を確認します。

  • 「太郎さん」のデジタル証明書の正当性を確認します。発行者に書かれている「中川さん」のデジタル証明書の公開鍵を使って検証します。
  • 「中川さん」のデジタル証明書の正当性を確認します。発行者に書かれている「山中さん」のデジタル証明書の公開鍵を使って検証します。
  • 「山中さん」のデジタル証明書の正当性を確認します。発行者に書かれている「信夫さん」のデジタル証明書の公開鍵を使って検証します。
  • 「信夫さん」のデジタル証明書の正当性を確認します。発行者に書かれている「信夫さん」のデジタル証明書の公開鍵を使って検証します。

このように証明書を順に検証して、最終的に信頼できるルート証明書にたどり着いたら、太郎さんの公開鍵は正当であるといえます。

証明書チェーンの具体的な例ですが、ウェブブラウザの鍵マークをクリックして開くことができるサーバ証明書の表示内容から確認することができます。Windowsであれば「証明書のパス」のタブから証明書構成を表示してみてください。複数の異なる発行者による証明書構成を確認することができます。

証明書チェーンサンプル

デジタル証明書の種類

では次に、デジタル証明書の種類について説明します。

デジタル証明書は利用用途によって主に3つに分類することができます。

  • サーバ証明書
  • クライアント証明書
  • コードサイニング証明書

サーバ証明書

サーバ証明書は、クライアントが正しいサーバに接続していることを確認するために使用します。 クライアントはルート証明書を事前に保持します。そして、サーバはサーバ証明書を保持します。

TLS通信接続するときに、サーバがサーバ証明書をクライアントに送信します。もし中間CA証明書を使用している場合は、サーバ証明書に連結して送信します。

クライアントは、ルート証明書を使って受信したサーバ証明書が正当であることを確認します。正しいことが確認できれば、サーバ証明書に含まれている公開鍵を使って、サーバ-クライアント間で暗号通信を行います。

TLS通信ではこのサーバ証明書による認証は必須要件です。(厳密な仕様上ではオプションですが、特殊な使い方に限定されるので、ここでは必須としています。)

image-20211004144213373

サーバはサーバ証明書に含まれている鍵のペアとなるプライベート鍵を保持する必要があります。TLS通信時にこのプライベート鍵を使って通信の暗号化(鍵交換)を行うことになります。このプライベート鍵が漏洩すると、第三者がこのサーバになりすますことが可能となるため、セキュアに管理することが重要です。

そして、クライアントはそのサーバ証明書を検証することができるルート証明書を事前に保持する必要があります。

クライアントOSやブラウザでは、標準で保持しているルート証明書があります。例えばWindows10の場合、certlm.mscを起動すると、OSが保持している証明書を確認することができます。

もし、独自でプライベート認証局を立ち上げてサーバ証明書を作成した場合は、クライアント全員にルート証明書の事前配布が必要になります。クライアント環境で常に保持しているルート証明書を使って検証できる証明書を発行すれば、ルート証明書を配布する手間を軽減することができます。

クライアント証明書

クライアント証明書は、サーバが正しいクライアントから接続していることを確認するために使用します。 クライアントは、クライアント証明書とプライベート鍵を事前に保持します。そして、サーバはルート証明書を保持します。

通信の時にサーバがクライアント認証を要求し、クライアントがクライアント証明書をサーバに送信します。

サーバは、ルート証明書を使って受信したクライアント証明書が正当であることを確認します。正しいことが確認できれば、通信を継続します。

TLS通信ではこのクライアント証明書によるクライアント認証のことを相互認証とも呼びます。クライアント認証はオプション要件です。

image-20211004145004447

クライアント証明書は、ログイン認証の手段の一つと置き換えるとわかりやすいです。クライアント証明書を使って認証すればTLS通信のたびにクライアントの正当性の確認が可能となります。

クライアントごとにユニークな鍵を事前に作成・保持して、クライアント証明書を発行する必要があります。クライアントが多いほど証明書管理の運用負荷が多くかかります。クライアントが少数であれば、自作のプライベート認証局を立ち上げて証明書発行しても対応できますが、クライアントが多くなる場合は、クライアント証明書発行のシステム運用の検討が必要になります。

クライアント証明書を検証するために使用するルート証明書は、クライアント認証する特定のサーバだけが保持して、検証に使用します。ルート証明書をクライアントに配布する必要はありません。

クライアント証明書の仕様は、クライアント証明書を検証するサーバが決めることになります。システムの特性に合わせて仕様を決めることができるので、独自のプライベート認証局を使って証明書運用する場合が多くみられます。

コードサイニング証明書

コードサイニング証明書は、ソフトウェア利用者またはソフトウェア更新プログラムが改ざんされていない正当なソフトウェアであることを確認するために使用します。

コードサイニング証明書の使い方は仕様で規定されておらず、ソフトウェア仕様によってそれぞれ異なります。例えば自己署名証明書をコードサイニング証明書として使うケースや、X.509仕様とは異なるベンダー独自仕様のケースもあります。

ここでは、ひとつの例として、ソフトウェア利用者また更新プログラムがルート証明書を保持するケースを挙げて説明します。

ソフトウェア作成者はコードサイニング証明書とその鍵ペアとのあるプライベート鍵を事前に保持します。 そしてソフトウェアリリース時にコードサイニング証明書と検証値をソフトウェアに同梱します。 ソフトウェア利用者またはソフトウェア更新プログラムはルート証明書を保持します。

ソフトウェア利用または更新の時に、ルート証明書を使ってコードサイニング証明書が改ざんされていないことを確認します。その後、コードサイニング証明書に含まれている公開鍵でソフトウェアの改ざん検証を行います。

image-20211004152534428

このように、コードサイニング証明書は、ソフトウェア開発者が改ざんされていないソフトウェアであることを証明するために使用します。

コードサイニング証明書では、ソフトウェア開発者がプライベート鍵を管理します。もしこの鍵が漏洩してしまうと、改ざんしたソフトウェアを正当なソフトウェアとして成りすますことができてしまいます。

コードサイニング証明書はソフトウェアを使用する人だけに渡すことができればよく、ソフトウェアの改ざん確認機能も一緒に開発することが多いため、自作のプライベート認証局で発行した証明書を使用するケースがよく見られます。例えばAndroidやWindowsアプリ署名用の証明書などです。

コードサイニング証明書の発行や暗号仕様は、利用するソフトウェアやOS仕様によってそれぞれ異なります。

デジタル証明書の特徴

ではこの3つのデジタル証明書のそれぞれの特徴について以下の表で比較します。

サーバ証明書 クライアント証明書 コードサイニング証明書
プライベート鍵所有者 サーバ クライアント ソフトウェア開発者
証明書検証者 クライアント サーバ ソフトウェア利用者、ソフトウェア更新プログラムなど
利用用途 クライアントがサーバを確認する サーバがクライアントを確認する ソフトウェア利用者がソフトウェアを確認する
対策できる脅威 クライアントが不正なサーバに接続する サーバが不正なクライアントに接続される 不正なソフトウェアを利用してしまう
証明書仕様 証明書登録局が設定 利用環境によって異なる ソフトウェアによって異なる

利用用途によって証明書の設計・管理・運用方法が異なってきます。

例えばコードサイニング証明書に関する仕様であるにもかかわらず、サーバ証明書の要件をそのまま流用してしまうと、頻繁に鍵を更新することになり、そのたびに証明書発行業務が発生して、その証明書管理(保管、配布)も必要となるというように、過剰な運用コストがかかってしまう場合があります。

利用用途に適したデジタル証明書の要件になっているかを確認するようにしましょう。

機能実装のポイント

デジタル証明書の検証機能を実装する場合は、実績があり、脆弱性対応を行っている、暗号ライブラリ・ミドルウェアを選択して利用するようにしましょう。

デジタル証明書の設計仕様は公開情報ですので、もし独自でソフトウェアを実装した場合でも、機能動作させることはできます。しかし、セキュリティ開発経験のある実装者でないと、脆弱性のあるソフトウェアになってしまうリスクが高くなるため、おすすめしません。

もう一つの注意点は、デジタル証明書の検証にはいくつか項目があるのですが、ソフトウェアによって検証内容が異なる場合があります。例えば、有効期限チェックが有効になっていないなどです。

開発段階では証明書検証の要件を明確にして、その要件を満たしているかどうかをチェックする必要があります。

検証エラーを想定したデジタル証明書を作成して、正しく検証できているか確認するようにしましょう。

まとめ

では今回の記事のまとめです。

  • デジタル証明書は、公開鍵を相手に渡すための手段である
  • ルート証明書は、改ざんされないように管理する必要がある
  • デジタル証明書は、利用用途によって設計・管理・運用方法が異なる
  • デジタル証明書の機能実装は、実績のある暗号ライブラリ・ミドルウェアを利用することが望ましい

おわりに

デジタル証明書の設計についてご紹介しました。いかがだったでしょうか?

セキュリティ機能として「デジタル証明書を使って検証できること」という要件が頻繁に出てきます。しかしデジタル証明書の使い方によって、鍵更新の有無や証明書発行など、コストとのトレードオフになる機能仕様があります。

製品開発の際は、まずデジタル証明書と暗号鍵を使って何を守るのか?をシステム設計時に意識して、デジタル証明書の運用も含めて検討することで、開発の手戻りや運用コストを減らすようにしましょう。

デジタル証明書を使った開発の手助けとなれば幸いです。

参考リンク