【図解】初心者も分かる”公開鍵/秘密鍵”の仕組み~公開鍵暗号方式の身近で具体的な利用例やメリット〜

前提

公開鍵暗号方式にはいくつか種類があります。この記事で出てくるのは『RSA』と『Diffie Hellman (DH) 鍵交換』の 2 つです。

RSA 公開鍵/秘密鍵でできること ~暗号化とデジタル署名~

まずは RSA の公開鍵/秘密鍵について説明します。

特定のサーバ A が秘密鍵を持ち、任意のクライアントがその対となる公開鍵 (サーバ A の公開鍵) を持っているとします。

公開鍵を使って暗号化すると秘密鍵でのみ復号できます。秘密鍵は原則サーバ A 以外には知られないため、サーバ A のみが復号化でき、機密性が確保できます

逆に、秘密鍵を使って暗号化すると、公開鍵でのみ復号できます。公開鍵は広く知られる前提であるため、機密性の確保はできませんが、「サーバ A の公開鍵で復号化できた」通信というのは、「発信源が間違いなくサーバ A であり、内容は改竄されていない」という完全性・真正性が確保できます

これは主に『デジタル署名 (Digital-Signature)』で使われます。

この性質を利用し、サーバに公開鍵及び秘密鍵をインストールすることで、以下のことができるようになります。

任意のクライアントから特定のサーバ A への通信の機密性確保

サーバ A に一対の公開鍵と秘密鍵をインストールします。そして通信をしたいクライアントが現れたら、そのクライアントに公開鍵を配布します。そのクライアントは通信内容を公開鍵で暗号化をした上でサーバ A へ通信します。

サーバ A は全てのクライアントの通信を、1 つの秘密鍵で復号化して中身を確認することができます。

一方、サーバ A 以外の全世界の機器は秘密鍵が無いので通信は復号できません。公開鍵では復号化出来ないので、公開鍵は盗聴されても影響ありません。

特定のサーバ A から任意のクライアントへの通信の完全性・真正性確保

送信元がサーバ A であること (真正性)、およびサーバ A からの通信が改竄されていないこと (完全性) を、任意のクライアントが検証できます。

サーバ A は通信を送るときに、その通信内容のハッシュ値を秘密鍵で暗号化したデータを一緒に送ります。

クライアントは通信内容のハッシュ値を計算しつつ、付加されたデータを公開鍵で復号化し、同じ値になるかを確認します。合致すればそれはサーバ A からの通信であり、通信内容は途中で改竄されていないということを意味します。

筆跡鑑定のように後から人を特定することができるので『デジタル署名 (Digital-Signature)』と呼ばれています。

最近ではビットコインの multi-sig が話題になりましたが、これは、ビットコインを使う際に、複数人 (例えば夫婦) による上記デジタル署名のサインが必要となる、デジタル署名の応用例です。

共通鍵暗号方式と公開鍵暗号方式の比較 メリット・デメリット

共通鍵暗号方式の代表格 AES と公開鍵暗号方式の代表格 RSA を比較します。

 比較項目 AES 共通鍵暗号方式 RSA 公開鍵暗号方式
暗号・復号速度 (計算負荷) 高速 (低負荷) 低速 (高負荷)
鍵をセットするタイミング 通信開始より前に共有 通信開始時に公開鍵を送付
クライアント数Nのときの
鍵の必要数
2N N+1
2030年以降でも使える強度
のbit数 (セキュリティ強度)
256bit 3072bit

一番身近な具体例 https (SSL/TLS) への応用

https (SSL/TLS) では通信の暗号化自体は共通鍵暗号方式を使いますが、その共通鍵の元ネタの交換には RSA とは異なる公開鍵暗号方式が使われます。具体的には『DH (Diffie Hellman) 鍵交換』が利用されます。

DH では上で説明してきたものとは異なるタイプの公開鍵 (DH 公開鍵) を使います。この DH 公開鍵はサーバとクライアントでそれぞれ異なるのですが、この 2 つの公開鍵を合体させて共通鍵を生成します。

ですが、DH には認証機能がなく、成り済ましに弱いため、RSA 公開鍵暗号方式による認証を行いながら共通鍵の交換を行います。

昔は共通鍵の元ネタを公開鍵だけで暗号化して送る方式も選べましたが、最近はセキュリティ上の理由から使われないようになっています。公開鍵を使って共通鍵の元ネタを交換すると、前方秘匿性が無くなるためです。

なので https (SSL/TLS) における RSA 公開鍵 (DH 公開鍵ではなく今まで説明してきた公開鍵暗号方式) は『認証』の用途のみに使われます。具体的には、『アクセス先の URL がデジタル証明書のコモンネームと合致するか?』と『デジタル証明書のルート証明書をクライアントが信頼済証明書として登録されているか?』を確認します。

このように公開鍵方式と共通鍵方式を両用することで、お互いのメリットをフルに活かしているのです。

例として Web サーバへの https アクセスを考えます。

Web サーバは『RSA 秘密鍵』と『RSA 公開鍵付き証明書 (デジタル証明書、より一般的にはサーバ証明書)』を持ち、クライアントはサーバへのアクセス時にサーバから RSA 公開鍵付き証明書を提示されます。

RSA 公開鍵付き証明書は『証明書本体』と『署名』に明確に分かれており、証明書本体には公開鍵が内包されています。一方、署名は、証明書本体をハッシュ化し、秘密鍵で暗号化したものです。

また、証明書本体には『コモンネーム』というサーバへアクセスする際の URL 名が書かれています。例えば www.yahoo.co.jp の Webサーバなら、コモンネームも www.yahoo.co.jp になります。

クライアントは署名付き証明書を受け取ると、以下を確認します。

  1. 証明書の発行元 (ルート) が信頼できるルート証明書かどうか (Windows であれば証明書ストアの『信頼できるルート証明機関』に登録されていること)
  2. 証明書自体が改竄されていないか (署名を公開鍵で復号したものと、証明書のハッシュ計算結果が同じになるか)
  3. 自身がアクセスしているサーバの URL のドメイン名が証明書のコモンネーム (あるいはサブジェクト代替名)と同じか

なお、https プロトコルのシーケンスは以下の通りです。

  1. クライアントがサーバへ https アクセス、その際、自身が使える暗号方式を通知
  2. サーバは最適な暗号方式を返信しらさらに署名付き証明書をクライアントへ提示
  3. クライアントはルート証明書の検証、証明書の改竄有無、アクセス URL とコモンネームの合否を確認
  4. ‎問題なければ、クライアントとサーバ間で DH 公開鍵方式により、共通鍵の素を共有、併せてサーバからは RSA 秘密鍵による署名をクライアントへ送付 (DH は成り済ましに弱いためデジタル署名で相手を認証する)
  5. クライアントと‎サーバはそれぞれ共通鍵の素から共通鍵を生成
  6. ‎暗号化通信開始

また、ケースとしては少ないですが、SSL/TLS にはオプションで、クライアントの認証を行うこともできます。

関連記事

TLSにおけるクライアント認証とは TLSの規格としては、サーバの認証は必須ですが、クライアントの認証はオプション扱いとなっています。サーバの設定によっては、クライアント証明書による認証を強制させることができます。 以下の図の左側は[…]

その他の有名な使用例 SSH への応用

SSH を使うための事前準備として、サーバ側ではまず最初に RSA 等の秘密鍵/公開鍵のペアを生成する必要があります。ここでは例として RSA 秘密鍵/公開鍵を使うこととします。

実際に SSH クライアントからアクセスを受けた場合、まずは DH 鍵交換により共通鍵を共有し、以降の通信を全て暗号化した上で、デジタル署名による認証を行います。

なお、共通鍵は時間経過とともに別の鍵に変えていきます。

SSH サーバの認証(ホスト認証)

SSH クライアントはクライアント側の DH 公開鍵を送信します。それを受けてサーバはサーバ側の DH 公開鍵を送信しますが、同時に『RSA 公開鍵』、『RSA 秘密鍵による署名』も送信します。

SSH クライアントは SSH サーバからの署名を RSA 公開鍵で検証し、相手が正しい通信相手だと認証するのです。これがホスト認証です。

なお、SSH クライアントは、それが初回アクセスであれば、SSH サーバの IP アドレスと紐付けて、その RSA 公開鍵をインストールします。TeraTerm の場合、以下のような画面が表示されます。"Continue" を押下するとクライアントに RSA 公開鍵がインストールされます。

次回以降、同じ IP へのアクセス時に、提示される公開鍵が変わると警告を出します。単にサーバを更改した場合は問題無いですが、身に覚えが無い場合、成りすましの可能性があるためです (その後の ID パスワード入力が漏洩し、正規のサーバに不正ログインされる可能性がある)。

例えば TeraTerm だと以下のような警告画面が出ます。本当に鍵を変えているのであれば "Replace the exist key with this new key" にチェックを入れ、"Continue" を押下し、鍵を置き換えます。

SSH クライアントの認証

ホスト認証が終わった後は逆に、SSH サーバが SSH クライアントを認証します。これには大きく 2 つのやり方があります。

1 つは ID パスワード認証、もう 1 つは公開鍵認証です。

SSH クライアントの ID パスワード認証

前述の通り、SSH ではまず鍵交換により共通鍵での通信暗号化が為されます。なので SSH クライアントの ID パスワード認証は、共通鍵で暗号化された状態でサーバへ送付されます。サーバはやはり共通鍵でその情報を復号し、ID パスワードが正しいかどうかを確認します。

SSH クライアントの公開鍵認証

SSH クライアントの公開鍵認証においては、ID パスワードを使わず、クライアントの公開鍵による認証を行います。

この方式を使うためには、SSH クライアント側でも事前に RSA 等の公開鍵/秘密鍵のペアを生成し、公開鍵を SSH サーバへインストールする必要があります。

例えば user-a というユーザが SSH アクセスするためには、サーバ側の "/home/user-a/.ssh/authorized_keys" に公開鍵情報を書き込んでおきます。

あとは SSH クライアントが『クライアント側の RSA 秘密鍵による署名』をサーバへ送信するだけです。サーバ側では RSA 公開鍵を前述の authorized_keys に保有していますので、これを使って署名の検証を行います。この検証に成功すれば SSH クライアントが正しい (正しい RSA 秘密鍵を持っている) と判断します。

秘密鍵のセキュリティ、パスフレーズの必要性

秘密鍵はとても重要なものであるがゆえに、メール添付等を含め、安易に複製すべきではありませんし、保護すべきです。Windows 等のいくつかのソフトウェアでは秘密鍵をエクスポートできないような保護設定があります。

また、OpenSSL コマンドや ssh-keygen コマンド等で鍵ペアを作成する際、秘密鍵にパスフレーズを付けて保護することもできます。

このパスフレーズによる保護は、もし秘密鍵の利用タイミングが手動実行時のみであれば、利用のたびにパスフレーズを入力すればそれで問題ありません。

ですが例えば Apache の https 用秘密鍵をパスフレーズで保護している環境において、Web サーバが予期せず再起動してしまった場合はパスフレーズの入力を求められ、手動で打ち込まないと httpd が起動しません。

なので自動で秘密鍵が利用されることを期待する環境においては、パスフレーズを設定してはいけいません。

一方、人間がサーバ等の管理のために SSH 接続で秘密鍵を使う場合は、あった方がセキュリティは高くなります。

一見同じものとも思われがちですが、これはニ要素認証の考え方では、異なるものです。二要素認証では、認証の要素として『何を知っている?』『何を持っている?』『何者なのか?』といった種類の中から異なる 2 種類の要素に合格することで認証成功にする、という考え方をします。(同じ要素の中で 2 回認証するものを 2 段階認証と言います)

パスフレーズは人間が頭の中で覚えておくのが前提なので『何を知ってるか?』に該当します。一方、秘密鍵の内容は人間が覚えきれるものではなく、『何を持っているか?』に当たります。(具体的には秘密鍵のファイルそのもの)

このように、パスフレーズを設定した秘密鍵を使うことで、二要素認証を実現しているのです。

※ちなみに、『何者なのか?』は主に静脈認証や網膜認証等の生体認証のことです。

IT/インフラエンジニアの地位とスキル向上のために

関連記事

IT 技術の進化はとどまることを知りません。矢継ぎ早に新たな技術が出てきたり、数年前の技術が時代遅れになったりと、IT エンジニアは勉強し続ける運命のようです。 それをどう思うかはあなた次第。 ビジネスの基本は『付加価値を与える[…]

IMG
関連記事

nesuke の考える NW エンジニアの2つの道 ネットワークエンジニアには 2 つの道があります。 1 つはネットワーク構築一筋で、L4 までをひたすらきっちりと構築していく道。 もう 1 つはネットワークを軸として深堀し[…]

IMG