Open10

「TLS通信わからない」を卒業する

MenToRiMenToRi

TLS通信がなんとなくしかわからない。「サーバーとクライアント間で共通の鍵を生成してセッション間では同じ鍵で暗号化して通信しようね」くらいしかわかってない。


画像引用: https://www.toritonssl.com/about_ssl/ssl.html

[現時点での疑問]

  • 認証局ってだれ?どこにいるの?サーバーの中?
  • それぞれの公開鍵で暗号化したら、鍵自体はオープンだよね?となると誰でも公開鍵で複合もできちゃうから暗号化の意味がないよね?
    • つまりどちらかor双方の秘密鍵が必要だけど、秘密な時点でそれで暗号化したら復元できなくない?
    • つまり共通鍵ってどうやって作られてるの?
MenToRiMenToRi

認証局について

まず認証局について。

信頼された第三者機関「認証局」による保証

改ざん防止となりすましの防止については、SSL証明書を発行する「認証局」という組織の存在が重要になります。認証局はサーバーでもパソコンでもない第三者機関であり、「○○.jpドメインを保有している人にSSL証明書を発行しました」と保証してくれる組織です。

参照: https://ssl.sakura.ad.jp/column/ssl/#prevention

どこかの電子認証発行機関のこと。全然サーバーの中にいる人じゃなかった。

証明書は正確には「SSLサーバー証明書」や「CA証明書」のことを指し、数あるデジタル証明書のうちの一つを指す。この辺は用語解説。

MenToRiMenToRi

ルート証明書について

サーバー証明書との違いすら認識してなかった。

サーバー証明書は認証局が発行してそのサーバーの信頼性を担保しているが、では認証局の信頼性はだれが担保しているのか?というと、そのさらに上位の認証局が担保している。
ではその上位の認証局の担保は〜...と繰り返していくと、最終的に 自分で自分の信頼性を担保している認証局 にたどり着き、これを ルート認証局 と呼ぶ
ちなみにルート認証局によって担保されている中間の認証局のことを 中間認証局 と呼ぶ。そのまんまだね。

そしてクライアントにはあらかじめ信頼できる認証局の証明書がインストールされており、この証明書と照合することでルート認証局の信頼性を確認し、すなわちサーバーの信頼性を確認できる、という仕組み。

ここでのクライアントとはOSを指しており、ブラウザはこの証明書を参照する。
なお、Mozilla Firefoxは独自の証明書ストアを持っているため、OSにインストールされた証明書を利用しない模様。

ただし、ブラウザの中でもMozilla Firefoxは独自の証明書ストアを持っているため、OSにインストールされた証明書を利用しません。そのため、「Chromeでは閲覧できるのにFirefoxではSSLのエラーが表示されて閲覧できない!」といったサイトが稀に存在することがあります。

参照: https://ssl.sakura.ad.jp/column/difference-in-ssl/#trust-root

MenToRiMenToRi

ちなみに、すべてのサーバーをルート認証局で認証することはできるがなぜ中間認証局を用意しているのか。それは 失効リスクの分散 が目的である。

さて、なぜSSL証明書には公開情報である中間CA証明書が必要なのでしょうか?そもそも技術的には、ルート証明書の秘密鍵でサーバー証明書に直接署名することが可能です。前述の通り、ルート証明書はPCなどに直接ファイルとして保存されており、更新や削除が非常に難しくなっています。もし、ルート証明書で署名されたサーバー証明書を大量に失効する必要があった場合、無数にあるPCやスマートフォンからルート証明書を削除するか、大量のサーバー証明書を1つ1つ失効処理しなければなりません。ルート証明書は有効期間が非常に長いため、時間が経つにつれて署名されるサーバー証明書の数が膨大になり、このような失効処理時の影響が大きくなります。

そのような影響拡大を抑えるため、間に中間CA証明書を挟んでサーバー証明書に署名する階層構造を構成し、ルート証明書よりも有効期間を短く※することでルート証明書を直接削除・失効するリスクを分散しています。これが中間CA証明書の目的です。

参照: https://ssl.sakura.ad.jp/column/difference-in-ssl/#intermediate

MenToRiMenToRi

【サーバー側での証明書の準備の流れ】


画像引用: https://milestone-of-se.nesuke.com/sv-advanced/digicert/digital-certification-summary/

  1. サーバ秘密鍵を用意する。用意した秘密鍵から証明書署名要求 (CSR[1]) を作成する
  2. 証明書署名要求 (CSR) と公開鍵を認証局に送信する
  3. 認証局から署名されたサーバ証明書が送られてくる
  4. サーバ秘密鍵とサーバ証明書をサーバに設置する
脚注
  1. CSR とは証明書発行要求 (Certificate Signing Request) と呼ばれるもので、これを生成する際に、秘密鍵と公開鍵も作られます。CSR には公開鍵が含まれており、この CSR を中間認証局に送り、中間認証局の秘密鍵で生成した電子署名 (CSR をハッシュ化したものを秘密鍵で暗号化) を CSR の末尾に付け加えることでデジタル証明書が出来上がります。(参考: https://milestone-of-se.nesuke.com/sv-advanced/digicert/digital-certification-summary/) ↩︎

MenToRiMenToRi

暗号方式について

TLS通信では以下の2つの暗号方式が用いられている。

  • 共通鍵暗号方式
  • 公開鍵暗号方式

共通鍵暗号方式

暗号化と復号化に同じ鍵を使う暗号化方式 のこと。
お互い同じ鍵を使う必要があるので送信する必要があり、この通信も暗号化する必要がある。もしくはそれぞれの手元で同じ鍵を生成する方法もある。(鍵交換プロトコル(後述?))

公開鍵暗号方式

暗号化と復号化に別の鍵を使う暗号化方式 のこと。「公開鍵」と「秘密鍵」の2つの鍵が必要。

  • 公開鍵は全世界に公開してもOK
  • 秘密鍵は他人に知られてはならない

よく南京錠の例で取り上げられますね。
公開鍵が南京錠、秘密鍵がその鍵に対応。暗号通信を行いたい側は南京錠を配布し、通信相手は送信データにその南京錠をかけて返送する。受け取った側は秘密鍵を使って復号し内容を確認する、という流れ。
仮に通信を傍受されようと南京錠の鍵を持っていないと中身が見られないので安全、という仕組み。

現時点での疑問における

それぞれの公開鍵で暗号化したら、鍵自体はオープンだよね?となると誰でも公開鍵で複合もできちゃうから暗号化の意味がないよね?

が解消されたかな?公開鍵では複合ができないのでバラまいても大丈夫。

MenToRiMenToRi

TLS通信について

TLS通信の流れ

  1. クライアント(ブラウザ)からHTTPSリクエストがサーバー側に届くとSSLプロセスを開始。
  2. あらかじめサーバーに配置しておいたSSL証明書をクライアントに送信。SSL証明書はサーバーの正当性が認められれば認証局から発行されるもので、認証局の署名や公開鍵などが含まれている。
  3. ブラウザに最初から同梱されている世界的に認められた認証局(ルート認証局)のルート証明書とサーバーから送られてきたSSL証明書を照合する。一致すればサーバーから送られたSSL証明書が正当な認証局から発行されたものだと判断する。SSL証明書を発行した認証局が上位の認証局から認証を受けている場合は、ルート認証局までの証明書がサーバーから送られる。そしてルート証明書から順に証明書を検証する手順となる。
  4. クライアント側で共通鍵を生成する。SSL証明書に同梱されていた公開鍵を使ってその共通鍵を暗号化しサーバーに送る。
  5. 認証局から発行された秘密鍵を使ってクライアントから送られてきた共通鍵を復号する。
  6. クライアントとサーバー双方で共通鍵を持つことができたので、あとは共通鍵を使ってデータを暗号化/復号化して通信する。
  7. ⑥と同じ。

参照: https://btj0.com/blog/web/https-ssl-tls/

公開鍵暗号方式で共通鍵をサーバーへ送信し、以降の通信は共通鍵暗号方式で行う という流れですね。非常にわかりやすいサイトから引用しました。

MenToRiMenToRi

「鍵そのものの中身がどうなっているのか?」が理解できてないため「共通鍵を生成する」がピンと来てない。でそれを暗号化する、というところもピンと来てない。
(ただ、おそらくゴリゴリの数学が使われている箇所だと思うので深掘りしてもボコられて泣きながら引き返すことになりそう。余裕があったら調べようね。)

MenToRiMenToRi

また、この共通鍵を公開鍵暗号方式で送信する、という鍵交換はセキュリティ面(Forward Secrecy)の観点からTLS通信での利用は現在(TLS1.3~)では推奨されていない模様?

代わりに鍵交換プロトコル(鍵交換アルゴリズム)が利用されている(後述?)

(とはいえ色々なサイト調べると、大体この公開鍵方式で鍵交換するものがまとめられてますね)

MenToRiMenToRi

【公開鍵暗号方式と共通鍵暗号方式を使い分ける理由】
両者を比較した時、以下の特徴を持つ。

  • 公開鍵方式は安全性が高く、処理速度が遅い
  • 共通鍵方式は安全性が低く、処理速度が早い

生成した共通鍵は傍受されると通信が筒抜けになるので時間をかけてでも安全に公開鍵方式で送信し、以降の通信は速度を重視して共通鍵方式で行う、という両立を図っている。

ちなみにそれぞれの処理速度は15,000倍ほど差がある[1]ようです。かなりの差がありますね...。

脚注
  1. (参考: 『Real World HTTP 第2版』- https://www.oreilly.co.jp//books/9784873119038/) ↩︎