Web初心者の為のSSL/TLSまとめ 〜HTTPSって安全なの？〜

#はじめに
昨今IOSアプリもHTTPSが強制になりましたので、この辺でHTTPSについてまとめます。
前回 AWS ACMというHTTPS通信を行う為の証明書発行について記事を書いたのですが、
HTTPS通信を使えるようにしたのは良いですが、HTTPS通信ってどれくらい安全なの？という疑問を解決するために、SSL/TLSについて調べたのでまとめてみました。

---
ちなみに、この記事は基本的に「暗号技術入門 第3版 秘密の国のアリス」 という書籍で勉強した内容を参考にしています。
まだ読み始めですが、小難しい暗号の話をすごく分かりやすくまとめてくれていてかなりお勧めできる書籍だと思うので、この記事の内容に興味を持たれた方は暗号技術入門を読んでさらにセキュリティについての知識を深めると良いかと思います。

いつになるかわからないですが、読み終わったら書評を書きたいなーと思います。

---
#SSLとTLSの違い
では、まずはSSL/TLSってよく聞くけど、SSL/TLSってなんなの？ってお話。
簡単に言うと TLSバージョン1.0 = SSLバージョン3.1 という関係にあります。
SSL3.0で脆弱性が発見されたので、対策を施したものがTLSだそうです。
SSLという名前が広く普及していたため、今でもSSL/TSLって表記する事が多いらしいです。
※この記事では、以下TLSと記述します。

---
#TLSで保障できる事

---
一般的にTLSでは下記を保障する事ができます。

| 名前 | 意味 |
|:-: |:-: |
|  機密性 |  第3者に「盗聴」される事無く機密情報を相手に届けられる |
|  正真性 |  第3者に情報を「改竄」されていない事を保障する |
|  認証   |  通信相手が意図している相手だと保障する |


---
これらをどうやって、保障しているかを簡単に書くと下記のようになります。

| 名前 | 保障方法 |
|:-: |:-: |
|  機密性 |  公開鍵暗号 |
|  正真性 |  MAC: Message Authentication Code (メッセージ認証コード)|
|  認証   |  デジタル署名 |

---
#HTTPSとは？

---
では、TLSを使用する際に、よく使われるHTTPSとはなんなのか？
それは、TLSプロトコルに乗せたHTTPプロトコルの事を言います。
TLSの暗号化通信プロトコルにあやかって、HTTP通信を安全に行うわけですね。
他にもメールの送受信に使う SMTP　や POP3やファイル転送のFTPなどもTLSに乗せる事ができます。

---
#SSL/TLSのプロトコルについて

---
次に先ほどで説明したTLSプロトコルについても簡単に触れておきます。

TLSのプロトコルは「TLSハンドシェイクプロトコル」と「TLSレコードプロトコル」の2つのプロトコルが重なって構成されています。

---
- <b>上層のTLSハンドシェイクプロトコル</b>が暗号化以外の様々な処理を行います
    - TLSハンドシェイクプロトコルは下記の4つのプロトコルに分けて考える事ができます
        - ハンドシェイクプロトコル
        - 暗号仕様変更プロトコル
        - 警告プロトコル
        - アプリケーションデータプロトコル
        
- <b>下層のTLSレコードプロトコル</b>が上記の4つのプロトコルのデータに対して暗号化の処理を行います

![スクリーンショット 2016-08-15 0.20.13.png](https://qiita-image-store.s3.amazonaws.com/0/93763/97813e52-661c-fcf8-db98-3dc377564b4a.png)

---
#ハンドシェイクプロトコル

---
ハンドシェイクプロトコルは、実際に暗号通信を行う前にサーバー側とクライアント側で取り決めを行ったり、証明書や鍵の受け渡しを行ったりします。
簡単に言うと、暗号通信のやり取りをする前に行う準備をするプロトコルです。

ここで「証明書の交換」を行い、通信相手が正しい事を確かめ、後々安全に通信するために使用する「鍵交換」を行います。

---
##ハンドシェイクプロトコルが前準備として行っている事

---
ハンドシェイク時には下記のようなやり取りを行っています。

![スクリーンショット 2016-08-17 0.29.39.png](https://qiita-image-store.s3.amazonaws.com/0/93763/713b9e49-7843-ef52-5bc9-b236e45196cb.png)

その中でもフェーズ毎に行っている重要なポイントを簡単に説明します。

---
###<b>暗号方式を決める(第一フェーズ)</b>

クライアントによっては使用できる暗号方式が限られている場合があるため、クライアントが対応できる暗号方式を確認して、使用する暗号方式を取り決めます。

クライアント:「HELLO!僕が理解できるのはRSAと3DESだよ！」
サーバー：「了解！じゃあRSAと3DESでやり取りしますか」

---
###<b>証明書の確認(第二フェーズ)</b>

サーバー側が信用できる相手である事を確認します。

サーバー：「私、怪しい者ではございません。ほら、これが私の証明書です。」
クライアント:「ほほう、よろしくお願いします。」

---
###<b>共通鍵の交換(第三フェーズ)</b>

後々TLSレコードプロトコルが暗号通信に使用する共通鍵を交換します。
※ diffie-hellman鍵交換の場合、プレマスターシークレットという共通鍵を生成するための材料を交換します。

クライアント:「じゃあ、合鍵渡しときますね」
サーバー:「あ、ありがとう(//▽//)・・・ (ドキドキ)」

---
###<b>暗号切り替え(第四フェーズ)</b>

ここで、ハンドシェイク終了前に実際に暗号方式を切り替えます。
この時にすでに切り替えた暗号方式でFinish通信を行い、問題なく暗号方式が支えているかも確認が行われます。

クライアント:「暗号方式切り替えたよ、じゃあ終了しようと思うけど通じてるよね？」
サーバー:「通じてるよー、こっちも切り替えて終了するねー」

---
#暗号変更プロトコル

---
暗号変更プロトコル、先ほどの第四フェーズで実際に暗号を切り替えていたプロトコルです。
ハンドシェイクプロトコルが暗号方式を決めた後に、暗号方式を変える役目を担います。
暗号方式を変更する前は、「暗号なし」という方式でやりとりを行っているため、ここで「暗号なし」から<b>暗号変更を行う</b>という意味で暗号変更プロトコルと言うそうです。

クライアント:「じゃあ「暗号なし」から先ほど決めたRSAと3DESの暗号方式に変換しますね」
サーバー:「では、私も変更しますー」


---
#警告プロトコル

---
警告プロトコルはハンドシェイクプロトコルが事前準備を行う際に問題が起きた場合に、エラーを通信相手に伝えます。

サーバー:「うまく複合化できなかったよ」
クライアント:「Oops!」

---
#アプリケーションプロトコル

---
アプリケーションプロトコルはアプリケーションのデータ通信をやり取りします。
HTTPSの場合、TLS上にHTTPプロトコルが乗っかる形になるので、HTTPの通信はこのアプリケーションプロトコルを通ってやり取りされます。

クライアント:「HTTPでリクエストを送るねー」
サーバー:「HTTPだねーOK」

---
#TLSレコードプロトコル

---
TLSレコードプロトコルは上記の4つのTLSハンドシェイクプロトコルのデータを暗号化するプロトコルです。
ハンドシェイクプロトコルで暗号方式が決まり、暗号変更プロトコルが暗号方式の変更を行った時点で、その暗号方式に添った暗号化を行います。
ちなみに、ハンドシェイクプロトコルで暗号方式が決まるまでは「暗号なし」という方式でやり取りします。

---
HTTPSで例えると、HTTPプロトコルを使用したアプリケーションプロトコルを、TLSレコードプロトコルが暗号化して通信を行っているイメージ。

---
##TLSレコードプロトコルの処理フロー

---
TLSレコードプロトコルは下記図の様に暗号化処理を行います。
<img width="336" alt="スクリーンショット 2016-08-16 13.17.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/93763/cdb14d66-eb7c-d03f-39bc-105324308b39.png">

---
###<b>メッセージのフラグメント化</b>

まずは相手に送りたいメッセージを複数に分割(フラグメント化)します。

---
###<b>フラグメントの圧縮</b>

こんどはフラグメント化したメッセージを相手と合意した圧縮アルゴリズムで圧縮します。

---
###<b>MACの付加</b>

圧縮したフラグメントにMAC(Message Authentication Code)を付加します。
MACとはフラグメントの内容を共通鍵でハッシュ化したものです。

---
このハッシュ化は一方向ハッシュ関数で行われ、一方向ハッシュ関数は下記特性を持っています。

| 特性 |
|:-:|
| 同じ原文からは同じハッシュ値が得られます  |
| ハッシュ値から原文を再現することはできません。　  |
| 同じハッシュ値を持つ異なるデータを作成することは極めて困難です。  |

---
この特性を活かして、メッセージの受信側は送信側が行った、ハッシュ値作成手順をふみ、
フラグメントの内容をハッシュ化します。
そして、同じ原文からは同じハッシュ値が得られるはずなので、出来上がったハッシュ値が受信したハッシュ値と同じであるかを確認し、改竄されていない事を保障します。

---
図：[wikipedia参照]
(https://ja.wikipedia.org/wiki/%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E8%AA%8D%E8%A8%BC%E7%AC%A6%E5%8F%B7)
![661px-MAC.svg.png](https://qiita-image-store.s3.amazonaws.com/0/93763/93f6083a-f7bd-6f6f-903e-167af4c6d0ac.png)

※この図では メッセージとMAC(メッセージをハッシュ化したもの) が受信側に送信され、受信側は同じようにメッセージをハッシュ化し、先ほど受信したMACと比較している事が分かるかと思います。

---
###<b>暗号化</b>

MACを付加出来たら、メッセージとMACをまとめて共通鍵で暗号化します。
<img width="473" alt="スクリーンショット 2016-08-16 11.20.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/93763/9809b849-2199-5cc8-c9d4-131bc4af05c2.png">

---
###<b>タイプ・バージョン番号・データ長を付加</b>

最後にタイプ・バージョン番号・データ長の情報を付加して暗号化の完了です

| 情報 | 内容 |
|:-:|:-:|
| タイプ   | 4つプロトコル(ハンドシェイク・暗号仕様変更・警告・アプリケーションデータ)のうちのどのプロトコルのデータなのかを指定|
| バージョン番号  | SSL/TLSのバージョン情報  |
| データ長  | データの大きさ  |


---
#脆弱性について

---
TLSの仕組みに説明してきましたが、最後に脆弱性について少し説明します。

過去にはPOODLE攻撃の脆弱性や、HeatBleed脆弱性などがあったそうですが、
それ以外にもTLSで使用している暗号技術の脆弱性がそのままTLSの弱点へと繋がります。

---
しかし、TLSの特徴として、特定の暗号技術に依存しないフレームワークであるという特徴があります。
そのため、特定の暗号方式が弱い事が判明したら、他の暗号方式を使えば良いというメリットがあります。
この事を念頭において、なにか問題が見つかればすぐに対応できるように心がける事が大事です。

---
#最後に

---
今回、証明書発行をきっかけに、なんとなく安全だと理解していただけのHTTPSって実際どれくらい強固なセキュリティなの？という疑問について、かなり解消されました。
結論から言うと、HTTPSはかなり安全だという印象でした。

---
ただし、今回勉強してみて、そんなTLSでもこれまでいろんな脆弱性が見つかっている事や、重要なデータをやり取りしている分狙われやすいという印象を受けました。
あまり過信しすぎず、何が守れるのかをちゃんと理解する事がセキュリティを強化する上では大切だと実感する事ができたので、これを機にセキュリティについて少しでも理解を深めていこうと思います。

---
#関連

前回、AWSで無料証明書を発行した時の話
[AWSでSSL証明書を発行ACMの話とSSLとDNS等について](http://qiita.com/kinpira/items/8cb904a7f12b379a4b81)