---

1. セキュリティの重要性

セキュリティのCIA

以下の3要素(CIA)を維持する必要がある

  • 機密性(Confidentiality)
    • 情報が意図した相手以外に漏れていないこと
  • 完全性(Integrity)
    • 情報が誰にも改竄されていないこと
    • (機密性があったらこれも担保されるのでは?)
  • 可用性(Availavility)
    • 使用したいときに使用できること

上記のCIAを脅かす攻撃はさまざまなものがある。

これを理解する上で、脅威モデルという考え方に沿って見ていくとわかりやすい。

代表的な脅威モデルの考え方には、microsoft社の “STRIDE” がある

  • STRIDE
    • なりすまし(Spoofing)
    • データの改ざん(Tampering)
    • 否認(行為者が悪事を認めないこと)(Repudiation)
    • 情報漏えい(Information Disclosure)
    • サービス不能(Denial of Service)
    • 権限の昇格(Elevation of Privilege)

2. SSL 通信とは

なぜSSL通信が必要か?

サービスを提供する上で、STRIDEで考えたさまざまな攻撃手法考から防御する必要がある。

ここでは、守る対象を「通信」に限定して考えてみる限定して考えてみる。

データ通信のセキュリティでは、以下の4点に気をつける

  • 「盗聴」されてもデータが読めない様にする
  • 「改ざん」されてもそれを検知できるようにする
  • 「なりすましされてもそれに気づける様にする
  • 「否認」されない様に、本人でしか送付できない情報形式にする

「盗聴」への対策: 暗号化

暗号化というセキュリティ技術が使える。

2者間でルールを定め、ルールに従ってやり取りする情報を変更し、「2者間でしか読めないデータ」でやり取りする。

暗号化のルール方式は大きく分けてルール方式は大きく分けて2つある。

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

共通鍵暗号方式

2者間で暗号化アルゴリズムを決定し、共通鍵と呼ばれる特定のデータを取り決める。

それぞれの間で、同じ鍵を用いてデータを暗号化、復号化する方式。

ただし、この方式には以下の課題がある

  • 鍵の受け渡しをどう行うか
  • やり取りの相手ごとに鍵を作成、管理する必要がある
    • n人でデータをやり取りする際、n(n-1)/2 個 鍵が必要…

上記の課題を補うべく登場したのが、2点目の公開鍵暗号方式

公開鍵暗号方式

暗号化と複合化でそれぞれ使用する鍵が異なる。

具体例として、ボブからアリスに通信を行う状況を想定する。

ボブはアリスが公開している鍵で情報を暗号化して、アリスに渡す。

アリスは、秘密鍵で受け取ったデータを複合化してボブからの情報を取得する。

この場合、n人でデータをやり取りする場合、公開鍵と秘密鍵を合わせて2n種類あれば良い。

ただし、暗号化と復号化で鍵が異なるため計算に時間がかかるというデメリットがある

ハイブリッド暗号化方式

共通鍵暗号方式と公開鍵暗号方式の両方を組み合わせた方式。

最初の鍵交換を公開鍵暗号化方式を用いる。

送り主は共通鍵を作成、受信者の公開鍵で暗号化。

受信者は自分の秘密鍵で複合化、共通鍵を取り出す。

その後は共通鍵暗号方式を用いる。

やり取りの後は鍵を廃棄(同じ共通鍵を管理、再利用しない。

SSLプロトコルはこのハイブリッド暗号方式を採用している

「改ざん」の対策: MAC(メッセージ認証符号)

MACとは、データの完全性を保証するために使用するもの。

受信者がメッセージの改竄や偽造を検出できるようにする。

  • 必要なコンポーネント:
    • 送信者と受信者が事前に共有している共通鍵(秘密鍵)
    • メッセージ認証コード生成アルゴリズム(MACアルゴリズム)
    • メッセージ本体(改竄検知対象データ)
## 正常な通信フロー

送信者                                受信者
  |                                     |
  | 1. メッセージ準備                    |
  |    "残高: 1000円"                   |
  |                                     |
  | 2. MAC生成                          |
  |    HMAC(秘密鍵, "残高: 1000円")      |
  |    = "a1b2c3d4"                     |
  |                                     |
  | 3. 送信                             |
  |---> "残高: 1000円" + "a1b2c3d4" ---->|
  |                                     |
  |                                     | 4. MAC検証
  |                                     |    HMAC(秘密鍵, "残高: 1000円")
  |                                     |    = "a1b2c3d4" ✓
  |                                     |
  |                                     | 5. 検証成功
  |                                     |    メッセージ受理


## 改ざん攻撃のケース

送信者              攻撃者                受信者
  |                   |                     |
  |---> データ送信 ---->|                     |
  |   "残高: 1000円"   |                     |
  |   + "a1b2c3d4"     |                     |
  |                   |                     |
  |                   | 改ざん実行           |
  |                   | "残高: 1000円"       |
  |                   |     ↓               |
  |                   | "残高: 100000円"     |
  |                   | (MACはそのまま)      |
  |                   |                     |
  |                   |---> 改ざんデータ ---->|
  |                   | "残高: 100000円"     |
  |                   | + "a1b2c3d4"        |
  |                   |                     |
  |                   |                     | MAC検証
  |                   |                     | HMAC(秘密鍵, "残高: 100000円")
  |                   |                     | = "x9y8z7w6" ≠ "a1b2c3d4" ✗
  |                   |                     |
  |                   |                     | 改ざん検出!
  |                   |                     | メッセージ拒否

鍵の準備段階

最初の握手で4つの鍵を作る:

クライアント → サーバー用:
├ 暗号化鍵: データを隠す
└ MAC鍵: データが本物か確認

サーバー → クライアント用:
├ 暗号化鍵: データを隠す  
└ MAC鍵: データが本物か確認

実際の通信

送信側(例:ブラウザ)

  1. メッセージ: “パスワード: 123456”
  2. 連番追加: “1番目: パスワード: 123456”
  3. MAC作成: HMAC(MAC鍵, “1番目: パスワード: 123456”) = “abc123”
  4. 結合: “パスワード: 123456” + “abc123”
  5. 暗号化して送信

受信側(例:サーバー)

  1. 受信データを復号化
  2. “パスワード: 123456” + “abc123” に分離
  3. 自分でMAC計算: HMAC(MAC鍵, “1番目: パスワード: 123456”)
  4. 結果が “abc123” と一致? ✓ 一致 → データ受理 ✗ 不一致 → 接続切断

送りたいデータと共通鍵を使ってMAC関数で算出したMAC値送りたいデータに付与する

受信者はデータと共通鍵を用いてMAC値を算出し一致するか確認。

データが送信時から変更されたかどうかを確認できる

このためには、、

  • データからMAC関数を通したとき、同じMAC値となること
  • MAC値から元データが推測できないこと

を満たす必要がある

「なりすまし」、「否認防止」への対策: デジタル署名

公開鍵暗号方式で盗聴再策をした時と逆のやり方。

送信者が、送信者しか持っていない秘密鍵を用いて署名を行うことで、受信者は公開鍵を用いてそれを確かめること用いてそれを確かめることが可能。

送信者だけが秘密鍵を持つ

→ 送信者だけが署名を作れる

→ 「確実に送信者が作った」と証明できる

通信への「攻撃」から情報を守る SSL

SSLは以下の3つの機能を提供する

  1. ハイブリッド暗号方式による情報の内容の暗号化
  2. MAC関数による改ざん検知
  3. デジタル署名による通信相手の認証

SSL 通信の仕組み・範囲

SSL の流れは大きく分けると2つのフェーズに分かれる

  • 前半: ハンドシェイク(公開鍵暗号方式で共通鍵を交換)
  • 後半: データ転送(共有鍵暗号方式で通信を暗号化)
【SSL通信の全体像】
クライアント                    サーバー
    |                            |
    |========ハンドシェイク========|
    | 公開鍵暗号で安全に準備        |
    |                            |
    |======データ転送フェーズ======|
    | 共通鍵暗号で高速通信         |

ハンドシェイクフェーズ

ハンドシェイクの目的は3つ

  1. 暗号化アルゴリズムの合意
  2. 暗号化に使用する鍵の確立
  3. 認証

上記を、大きく分けて4つのステップで実施する。

  • ステップ1: 使用するアルゴリズムの合意
  • ステップ2: サーバーの認証
  • ステップ3: データ転送で使用する鍵の確立
  • ステップ4: ハンドシェイクが正しく行われたことの確認
【ハンドシェイクの流れ】
クライアント                    サーバー
    |                            |
    |------ ステップ1 ----------->| アルゴリズム決定
    |<----- ステップ2 -----------| 証明書で身元確認
    |<----> ステップ3 <--------->| 共通鍵を安全に作成
    |<----> ステップ4 <--------->| 準備完了の確認
    |                            |
    |====== 暗号化通信開始 =======|

ステップ1: 使用するアルゴリズムの合意

クライアントとサーバーが対応している暗号方式を確認し、最も強力な方式を選択する。

クライアント: 「AES-256、RSA、SHA-256に対応してます」
サーバー: 「了解!AES-256とSHA-256を使いましょう」

この時合意するアルゴリズムは以下

  • SSLのバージョン
  • 暗号化スイート(以下をまとめて使用)
    • サーバー認証アルゴリズム
    • 鍵交換アルゴリズム
    • データ転送で使用するデータ保護用の共通鍵暗号方式アルゴリズム
    • データ転送で使用するデータの完全性を確認するためのMACアルゴリズム
  • 圧縮アルゴリズム

ステップ2: サーバーの認証

サーバーが地震の公開鍵を含む証明書を提示し、クライアントが本物のサーバーかを確認する。

【証明書確認】
サーバー証明書
├ 発行先: amazon.com
├ 発行者: 信頼できるCA
└ デジタル署名: ✓

クライアント: 「本物のAmazonだ!」

ステップ3: データ転送で使用する共通鍵の確立

ここでのゴールは、共通鍵(後述の4つの鍵)を作成、確立すること。

そのために、クライアント、サーバーのそれぞれにおいて共通の関数(KDF: Key Derivation Function)を使用し共通鍵を作成する。

同じ入力と同じ関数から作成されたものは、数学的には必ず同じものになるはずということに基づいて生成し、鍵自体は通信路には乗せない

  • KDFとは:
    • 入力:
      • 共有秘密(Pre_master_secret)
      • あるランダムな文字列(クライアント側、サーバー側)
    • 出力:
      • クライアント、サーバーそれぞれの共通鍵およびMAC鍵
【鍵生成の流れ】
共有秘密(Pre_master_secret) + 「あるランダムな文字列」
    ↓
┌─────────────┐
│  KDF関数    │
└─────────────┘
    ↓
【以下の鍵を生成】
- 暗号化鍵
- MAC鍵

以下の鍵は、データ転送で使用される。

  • 暗号化鍵
  • MAC鍵

上記の「あるランダムな文字列」はクライアントで生成する。

これは鍵の元になるため、サーバーの公開鍵を使用して暗号化してサーバーに送付する。

サーバーは受け取った後、自身の秘密鍵で復号化して「あるランダムな文字列」を取得する。

ただし、「あるランダムな文字列」のみを使用して鍵を生成すると、異なるセッションでも常に同じ鍵が作成されてしまう。

盗聴に成功した第三者が再度そのデータを送付しクライアントになりすませる可能性がある。

そのため、クライアントとサーバーそれぞれで作成した2つの乱数を鍵生成関数の入力に追加し、暗号化鍵とMAC鍵を作成する。

(本書 図2-7. SSL ハンドシェイクの流れ 1 を参照)

ステップ4: ハンドシェイクが正しく行われたことの確認

ステップ1~3が正しく行われたことを確認する。

具体的には以下を確認する

  • 今までのやり取りしたメッセージが改竄されていないこと
  • 暗号化鍵・MAC鍵としてクライアント、サーバー側それぞれで同じものが生成されていること

上記の実施のため、「ステップ3」で作成した共通鍵・MAC鍵を使用できる。

  • ステップ3で作成したMAC鍵: 今までのやり取りの改ざん確認のために使用
    • MACを用いた改ざん確認のためには、事前に秘密鍵の共有が必要だった。これをステップ3で実施完了している
  • ステップ3で作成した共通鍵: 改ざんの確認時のデータ送信時に使用

クライアント、サーバーのそれぞれが、自信が送信したメッセージをステップ3で作成したMAC鍵、最初に取り決めたMACアルゴリズムでMAC値を計算。

これをステップ3で作成した共通鍵で暗号化し送付し合い、検証を行う。

(本書 図2-8. SSL ハンドシェイクの流れ 2を参照)

SSL 通信で保証されるもの

  1. 転送中のデータ
    • 暗号化技術により、「盗聴」されてもデータを読むことはできない
    • MACにより、「改ざん」されてもそれを検知可能
  2. 通信相手が正しいマシンであること
    • サーバーの公開鍵の証明書により、「なりすまし」を見抜ける
    • デジタル署名により、「否認」を見抜ける

3. SSL通信の構築準備

SSLを実現する上で必要な要素は以下。

  • 証明書(Webサイトが安全であるということを外部に示す電子証明書)
  • 公開鍵・秘密鍵(Webサーバーで使用する暗号化・復号化のキー)
  • 暗号化アルゴリズム(データ転送時に用いる暗号化・復号化のルール)
  • SSL ライブラリ(SSLプロトコルを実現する暗号化・復号化モジュール)

証明書の種類

HTTPS における証明書とは?

HTTPSにおける証明書とは、「公開鍵」が「被証明者のもの」であることを証明する。

つまり、証明書に同梱されている公開鍵が信頼できる、ということを相手に伝える役目を持つ。

そのためには、証明書には以下の情報が必要となる。

  • 公開鍵
  • 被証明者の署名
  • 被証明者の情報(ドメインなど)

「被証明者の情報」には、一般的に3種類ある。

  • 第一段階: ドメイン証明
  • 第二段階: 法的な実在証明
  • 第三段階: 物理的な実在証明

※上記と厳密に対応するのか不明だが、SSL/TLSにおけるサーバー証明書の認証レベルは以下の通り

  • 参考
    • EV(Extended Vcalidation)証明書
    • OV(Organization Validation)証明書
    • DV(Domain Validation)証明書

自己証明書

状況:
• ボブとアリスが電話番号を交換済み
• 後日「アリス」から電話 → 100万円振込要求
• ボブは口座に見覚えなし

問題:
ボブ: 「本当にアリスですか?」
相手: 「アリスよ!この番号がその証拠でしょ?」
ボブ: 「でも声が違うような...」
相手: 「風邪ひいてるの。とにかく私がアリスだから信じて!」


これが自己証明書と同じ構造:

| 電話の例 | HTTPS自己証明書 |
|----------|----------------|
| 「私がアリスよ」 | 「私がamazon.comです」 |
| 電話番号だけが根拠 | 自己署名だけが根拠 |
| 第三者確認なし | CA確認なし |
| なりすまし可能 | 偽サイト可能 |

つまり、第三者による証明書が必要。これを行うのが CA (Certificat Authority: デジタル証明書を発行する認証局)

パブリック認証局による証明書

ドメインの正しさを証明する相手として、「認証局」と呼ばれる機関がある。

  • 具体例:
    • 適当なHTTPSのwebサイトをChromeで開き、SSL/TLS設定を確認する
    • 「証明書の階層」を確認
      • より上位の存在に証明してもらっていることがわかる
    • では、最も上位の存在は一体誰に証明してもらっているのか?
    • ブラウザに限らず、SSL上で接続するアプリケーションに同梱されている
      • 例えば、amazon.comは階層を辿るとDigiCertの証明に行き着く。これはChromeの証明書マネージャ>Chrome Root Store を見ると、DigiCertに関する証明書があることを確認できる

プライベート認証局による証明書

前提として、証明書の正しさは証明書階層を辿って行われ、最終的にブラウザに同梱された証明書に辿り着く

つまり、ブラウザに証明書リストさえ載っていれば、パブリックに認められた機関ではなくても警告の出ない証明書が発行できる、ということ

これが「プライベート認証局」による証明

  • 具体例:
    • 企業内で配布するPCのブラウザに、初期設定で企業内の認証局の自己証明書を登録しておく
    • これにより、その企業内PCであれば警告が出ることなくイントラ環境をSSLで使用可能

暗号化アルゴリズム選び

共有鍵暗号化方式

暗号化方式は通常SSLモジュール内に選択肢として用意されており、パフォーマンスや強度などの観点から選択する。

ここでは、共有鍵暗号化方式について取り扱う。

つまり、サーバーとクライアントがそれぞれ同一の鍵を使用する状況。

共有鍵暗号化方式の有名なアルゴリズムとしては以下

  • DES
  • AES
  • RC4

公開鍵暗号化方式

SSL通信では、ハンドシェイクフェーズで共通の鍵の元となるランダムな文字列の配送や、証明書によりwebサイトの正当性を示すために使用される。

有名なのは以下

  • RSA
  • DH/DSS

ハッシュアルゴリズム

ある入力に対して常に同じ値を出力し、入力に対して結果が偏らず一様に分布する性質を持つものをハッシュ関数と呼ぶ。

SSLでは、MAC(Message Authennication Code)アルゴリズムとしてハッシュアルゴリズムが用いられる

以下の3つが有名

  • MD5
  • SHA1
  • SHA2