Webエンジニアのブログ

プロフェッショナルSSL/TLSの基礎編をまとめてみる

TLSとかセキュリティに関して弱いなーと思っていたので『プロフェッショナルSSL/TLS』を買った。基礎的な知識から詳細までかなり詳しく書かれてて、相当読み応えがある本だと思う。

ということで基礎編である1~3章を後で読み返せるよう、自分なりにまとめておいた。

SSL/TLSと暗号技術

TLS(Transport Layer Security)はインターネット上で安全に通信するためのセキュリティプロトコルのこと。 TLSは前身のプロトコルの名称であるSSL(Secure Socket Layer)と合わせて、SSL/TLSと呼ばれることもある。

プロトコルの歴史

SSLプロトコルはNetscape社で開発された。SSLプロトコルの最初のバージョンは日の目を見なかったが、次のバージョンであるSSL2は1994年にリリースされた。しかしSSL2はセキュリティ専門家などに相談をしないまま開発されたため、重大な脆弱性が見つかった。そしてNetscape社は否応なくSSL3.0を1995年にリリースした。SSL3.0は根本から設計し直されており、TLSプロコトルの基本設計になっている。

1996年にSSLをIETFに移管するためのグループが結成され、1999年にRFC2246としてTLS1.0がリリースされた。そしてさらに2006年にTLS1.1がリリースされ、2008年にTLS1.2がリリースされた。2018年にはTLS1.3がIETFによって標準化された。

暗号技術

暗号技術は、安全な通信のための科学技術である。暗号技術を適切に運用すれば、秘密が守られること(機密性)、本人であることの検証(真正性)、データが改竄されていないこと(完全性)の3つの問題を解決できる。

共通鍵暗号化方式

共通鍵暗号化方式は、安全でない通信路を介して安全にデータを転送できるようにする難読化の方法である。

  1. AlliceとBobは、安全な通信に使う暗号アルゴリズムと秘密の鍵(以下、秘密鍵)についてお互い同意しておく
  2. Aliceは、Bobにデータを送るとき、その秘密鍵でデータを暗号化する
  3. Bobは、同じ秘密鍵を使ってデータを復号する

このように、攻撃者が秘密鍵をもっていない限り、安全に通信を行うことができる。

暗号は大きくストリーム暗号化方式とブロック暗号化方式に分かれる。

ストリーム暗号化方式

ストリーム暗号化方式とは、暗号アルゴリズムに1バイトの平文を流して、1バイトの暗号文にし、復号では逆の操作をするようなもののこと。 鍵ストリームというランダムなデータを生成して、そのストリームの1バイトと平文の1バイトとの排他的論理和を取ることで暗号化を行う。

ブロック暗号化方式

ブロック暗号化方式とは、データの塊(ブロック)をまとめて暗号化するもののこと。

ハッシュ関数

ハッシュ関数とは、任意の長さの入力を受け取って、固定長の出力へと変換するアルゴリズムである。ハッシュ関数が出力したものをハッシュ値と呼ぶ。 一般的なハッシュ関数と区別される暗号学的ハッシュ関数には、次のような性質が求められる。

  • あるハッシュ値から、そのハッシュ値になるメッセージを見つけることが計算論的に困難であること
  • あるメッセージとそのハッシュ値から、同じハッシュ値になる別のメッセージを見つけることが計算論的に困難であること
  • 同じハッシュ値が得られるメッセージを2つ見つけることが計算論的に困難であること

MAC(メッセージ認証コード)

ハッシュ値を使うと通信データの完全性を検証できるが、そのためにデータそのものとは別にハッシュ値を転送しなければならない。ハッシュ値をデータと一緒に転送すると、データとそのハッシュ値の両方を攻撃者によって捏造されるおそれがある。

そこでMAC(Message Authentication Code、メッセージ認証コード)、あるいは鍵付きハッシュと呼ばれるものが考案された。MACは一般に暗号処理と組み合わせて使われる。MACが使われていないと攻撃者は復号できなくともデータの改竄はすることができる。つまり機密性はあるが完全性がないことになる。暗号文と一緒にMACを送れば、メッセージの完全性を確かめることができる。

HMAC(Hash-based MAC)という仕組みを使うことで、どんなハッシュ関数でもMACに利用できる。HMACを要約すると、ハッシュ鍵を安全な方法でメッセージに織り交ぜる仕組みのこと。

暗号化利用モード

暗号化利用モードとは、ブロック暗号化方式を任意の長さのデータを暗号化できるようにした処理のこと。CBC(Cipher Block Chaining)モードはTLS1.3より前のバージョンで主に使われていたモード。CBCを改良したGCMモードはTLS1.2から利用できる。

公開鍵暗号化方式

公開鍵暗号化方式は、秘密鍵と公開鍵という2種類の鍵を使って暗号化する方法を取っている。

  1. BobはAlliceの公開鍵を使ってメッセージを暗号化する
  2. Alliceは秘密鍵を使ってメッセージを復号する

公開鍵暗号化方式は計算に時間がかかるため、大きなデータ送信には向いていない。そのため主に認証や、あとで使う共有鍵についてやり取り(ネゴシエーション)するときに利用される。

ディジタル署名

ディジタル署名とは、電子的なメッセージに対する真正性を検証可能にする暗号学的な手段のこと。前述したMACもディジタル署名の一種である。

ディジタル署名をするためには公開鍵暗号化方式を応用する。公開鍵暗号化方式の非対称性を利用して、秘密鍵で署名したメッセージを、対応する公開鍵で検証するアルゴリズムを作ればいい。RSAというアルゴリズムでは以下のような流れになる。

  1. メッセージのハッシュ値を計算する
  2. ハッシュ値にメタ情報(利用したハッシュ関数などの、受け手が利用する情報)を付加して符号化する
  3. 符号化したハッシュ値を秘密鍵で暗号化する

受け手が検証する際に、送り手が使ったのと同じアルゴリズムを使って独自にハッシュ値を計算する。次に送り手の秘密鍵に対応する公開鍵を使って署名を処理し、送り手が生成したハッシュ値を手に入れる。そして自分が生成したハッシュ値と比較する。

乱数生成器

暗号学の観点から言うと、セキュリティの全ては乱数生成器の品質にかかっている。というのも秘密鍵はとても長い乱数であるため、その乱数を作るとなると予測可能な動作をするというコンピュータの特性が問題になる。真の乱数と呼べるものは物理現象の観察結果からしか得られない。そこでコンピュータではエントロピーを集めるためにマウスの動きがキー入力を観察している。

しかし実際にはそれだけではエントロピーが足りないため、擬似乱数生成器を使う。擬似乱数生成器では、真の乱数生成器から得られる少量のデータを利用する。

暗号強度

暗号の強度は、暗号アルゴリズムを破るのに要する操作の回数を使って測定する。この暗号強度をビット安全性と呼ぶ。 現状、安全のためにできる一番簡単なことは、長い鍵による運用であるため、128ビット(1^128の操作)、もしくは256ビットを使うとよい。

MITM攻撃

トランスポート層に対する攻撃の大半は中間者攻撃(MITM攻撃、man-in-the-middle attack)という形態である。攻撃者が単に当事者の会話を聞いていることを受動的ネットワーク攻撃(受動的攻撃)と呼ぶ。攻撃者が積極的に通信内容を操作したり、通信内容に影響を与える場合、能動的ネットワーク攻撃(能動的攻撃)と呼ぶ。

アクセスの奪取

ケーブルや経由するルーターなどにアクセスできれば、誰でも経路を流れるパケットの中身を見たり妨害したりできる。最も簡単なMITM攻撃は、犠牲者が利用するネットワークに入り込み、その通信が攻撃者のノードを経由するように仕向けることだといえる。

ARPスプーフィング(ARP spoofing)

ARP(Address Resolution Protocol)は、MACアドレスをIPアドレスに関連付けるために利用されるプロトコルのこと。ネットワークにアクセスできる攻撃者は、任意のIPアドレスをMACアドレスアドレスに結びつけて経路を思い通りに変更することができる。

WPADハイジャック(WPAD hijacking)

WPAD(Web Proxy Auto-Discovery)プロトコルは、ブラウザがHTTPプロキシの設定を自動取得するために使われるプロトコルのこと。攻撃者は、ローカルネットワーク上でプロキシを起動し、それをプロキシを探しているネットワークのクライアントに通知することでWPADに対する攻撃が可能になる。

DNSハイジャック(DNS hijacking)

レジストラ(ドメイン名の登録申請を受け付ける組織)と共謀してドメイン名を則ったり、DNSの設定を変更することで、そのドメインに向かうトラフィックを攻撃者が乗っ取ることができる。

DNSキャッシュポイズニング(DNS cache poisoning)

DNSサーバーのキャッシュの脆弱性を悪用する攻撃により、攻撃者は不正なドメイン名の情報をキャッシュに流し込む。攻撃に成功すると、影響を受けるDNSサーバーの利用者すべてが不正な情報を受け取ってしまう。

BGP経路ハイジャック(BGP route hijacking)

BGP(Border Gateway Protocol)は、IPアドレスのブロックがどこにあるかをルーターが見つけるために利用されるプロトコルのこと。どこかのルーターで不正な情報を受け入れてしまうと、特定のブロック宛のトラフィックがすべて別の場所、攻撃者のもとにリダイレクトされてしまう。

受動的攻撃

受動的攻撃はトラフィックが暗号化されていない時に最も有効的な手段になる。暗号化されていたとしても、暗号化アルゴリズムに脆弱性が見つかるまでトラフィックを保存しておくこともできる。

能動的な攻撃

MITM攻撃は、Bobと話しているかのようにAliceに思い込ませるという認証をターゲットとしたものになる。MalloryはAliceからのメッセージを受信してそれをBobに転送する。TLSを使っている場合、攻撃者はAliceが有効なものとして受け取るような証明書を提示するのが理想的である。

プロトコル

TLSは、上位層の通信プロトコルが何であるかによらず、通信を安全にするために設計された暗号化プロトコルのこと。

Recordプロトコル

TLSを大まかにとらえると、Recordプロトコルによって実現されていると言える。Recordプロトコルがコネクション上でやり取りされる低レベルのメッセージの転送を全て担う(場合によっては暗号化も)。 TLSレコードの先頭には短いヘッダがあり、レコードのコンテントタイプ、プロトコルバージョン、レコード長などが格納される。そのヘッダのあとにメッセージのデータが続く。

Handshakeプロトコル

Handshakeプロトコルにより、TLS接続で使うパラメータのネゴシエーションと認証を行う。

フルハンドシェイク

クライアントが通信相手のサーバーとセッションを確立したことがない場合、両者はTLSセッションを確立するためにフルハンドシェイクを実行する。 フルハンドシェイクの間にクライアントとサーバーが行うことは主に4つある。

  1. 接続で使いたいパラメータを双方が提示し、互いに合意する
  2. 提示された証明書か、他の方法を使って認証を行う
  3. セッションの保護に使うマスターしクレットを共有する
  4. ハンドシェイクのメッセージが改竄されていないことを検証する

下記に最も一般的なハンドシェイクの例を示す。

  1. クライアントがサーバーへ、希望する暗号スイートや鍵交換の方法を送信する
  2. サーバーがパラメータを決定
  3. サーバーが自身の証明書チェーンを送信する
  4. マスターシークレットの生成に必要な情報があればクライアントへ送信する
  5. ネゴシエーションにおける自分の番が終わったことをクライアントへ通知する
  6. マスターシークレットの生成に必要な情報をクライアントから送信する
  7. クライアント側で暗号通信に切り替え、そのことをサーバーに通知する
  8. クライアントから送信および受信したハンドシェイクメッセージのMACを送る
  9. サーバー側で暗号通信に切り替え、クラアントに通知する
  10. サーバーから送信および受信したハンドシェイクメッセージのMACを送る
ClientHello

クライアントは、このメッセージを使って自分が希望するパラメータ群やその優先度をサーバーに伝える。クライアントがこのメッセージを送信するのは、新規にコネクションを開始するとき、再ネゴシエーションしたいとき、サーバーからの再ネゴシエーションに応えるときの3つになる。

ServerHello

サーバーは接続で使うパラメーターを選択し、それをクライアントに返答する。メッセージの構造はClientHelloと同じになる。

Certificate

Certificateメッセージは、主にサーバーからクライアントへ証明書チェーンを運ぶために使う。証明書チェーンは、エンコードされた証明書を順番に並べたものである(詳しくは3.4節で解説)。

ServerKeyExchange

ServerKeyExchangeメッセージの目的は、鍵交換に必要な付加的なデータを運ぶことである。このメッセージはネゴシエーションする暗号スイートに応じて異なり、何も送らなくてよい場合もある。

ServerHelloDone

ServerHelloDoneは、予定していたハンドシェイクをすべて送信したときにサーバーから送るメッセージである。

ClientKeyExchange

ClientKeyExchangeは、クライアントから送信する、鍵交換に必要な情報をクライアントから送信するためのメッセージである。

ChangeCipherSpec

ChangeCipherSpecは、クライアントとサーバー両方が送信するメッセージであり、暗号鍵を生成したこと、これから暗号処理へ移行することを相手に伝える。

Finished

Finishedは、ハンドシェイクが完了したというメッセージで、クライアントとサーバー両方が送信する。このメッセージは暗号化されている。 verify_dataというフィールドには、クライアントとサーバーのそれぞれが受信したハンドシェイクメッセージの全てをハッシュ化し、マスターシークレットと組み合わせて計算したものが入っている。

クライアント認証

クライアントとサーバーの相互認証は必須ではないが、サーバーはクライアントの認証を求めることができる。これを相互認証と呼ぶ。

セッションリザンプション

フルハンドシェイクは高負荷を要するため、セッションリザンプションを使ってオーバーヘッドを回避できる。セッションリザンプションは、SessionIDという識別子を使って、セッションの再開を可能にする仕組みである。セッションリザンプションに対応するサーバーはServerHelloメッセージにSessionIDを含めて返し、そしてクライアントはセッションの再開にこのSessionIDを使用する。そして以前共有したマスターシークレットを使って暗号鍵を生成し、暗号化通信へと移行する。

鍵交換

TLSでは、マスターシークレットと呼ばれる48バイトの鍵をサーバーとクライアントで共有する。ただし鍵交換の目的は、これとは違うプリマスターシークレットという値を生成することにある。そしてこのプリマスターシークレットの値からマスターシークレットを構成する。

TLSは多様な証明書や公開鍵アルゴリズム、鍵交換アルゴリズムをサポートしている。鍵交換アルゴリズムによく利用されるのはRSA、DHE_RSA、ECDHE_RSA、ECDHE_ECDSAなどがある。

RSA鍵交換

RSA鍵交換はクライアントがプリマスターシークレット(48バイトの乱数)を生成し、それをサーバーの公開鍵で暗号化してClientKeyExchangeメッセージで送信する。このメッセージを復号すれば、サーバーはプリマスターシークレットを入手できる。

ただし公開鍵に対応する秘密鍵を攻撃者が入手できれば、プリマスターシークレットを複合して同一のマスターシークレットを生成することができる。この問題は他の一般的な鍵交換の仕組みにはなく、この特徴をPFS(Perfect Forward Security)という。PFSがある鍵交換では、接続ごとに独立したマスターシークレットを利用し、過去にさかのぼって通信を復号されるという問題を回避する。

Diffie-Hellman鍵交換

DH鍵交換は、安全ではない通信路を介して共有の秘密を確立するためのアルゴリズム。受動的攻撃に対しては安全であるが、通信路を乗っ取って通信相手のふりをする能動的攻撃を受ける可能性がある。そのためDH鍵交換は、一般には認証と併せて利用する。

楕円曲線Diffie-Hellman鍵交換

ECDHE(ephemeral elliptic curve Diffie-Hellman)は概念としてはDH鍵交換に似ているが、中核となる数学的な基盤が異なる。

認証

TLSではコストの高い暗号処理を何度もしなくて済むように、認証が鍵交換と一体になっている。TLSの認証は、証明書を利用した公開鍵暗号化方式(RSAが一般的)を基本としている。証明書を検証した後、クライアントは公開鍵を使って相手を認証する必要がある。

RSAでは、クライアントがランダムな値をプリマスターシークレットとしてサーバーに送信し、サーバー側は秘密鍵を使って復号してクライアントへFinishedメッセージを送る。これによって暗黙に認証が行われている。

暗号化

TLSではアプリケーションデータをさまざまなアルゴリズムで暗号化できる。暗号化アルゴリズムには3DES、AES、ARIA、CAMELLIA、RC4、SEEDなどがある。2016年12月で最も一般的なのはAESである。

再ネゴシエーション

再ネゴシエーションが要求された場合、新しい接続のセキュリティパラメータについて合意するために改めてハンドシェイクを行う。サーバーが再ネゴシエーションを求める場合、HelloRequestメッセージをクライアントに送り、ハンドシェイクを始める。

暗号スイート

暗号処理のアルゴリズムやスキームを決めるパラメータを集めたものを、暗号スイートと呼ぶ。暗号スイートには以下のような属性が含まれている。

  • 認証の種類
  • 鍵交換の種類
  • 暗号化アルゴリズム
  • 暗号鍵の長さ
  • ...等

暗号スイートだけでセキュリティパラメータをすべて伝えるには不十分だが、特に重要なものは類推することができる。暗号スイートは300以上のものが公式に存在する。

拡張

TLSに機能を追加する汎用の仕組みがTLS拡張である。TLS拡張はClientHelloおよびServerHelloのメッセージ内のブロックで送信する。

プロトコルの限界

TLSには意図しない弱点や、OSIレイヤに起因する制限などがある。例えばTCPのメタデータおよび下位のレイヤはすべて平文のままであり、送信元や宛先のIPアドレスなどは誰でも判別できるようになっている。

公開鍵基盤

世界規模で使える公開鍵の基盤として、公開鍵基盤(PKI:Public Key Infrastructure)がある。

インターネットPKI

PKIとは、一般的にインターネットで使われるPKIのことを指す。PKIの目的はお互いにあったことがない者どうして安全な通信を実現することである。現在のPKIは、全員が無条件に信頼する証明書の発行をCA(Certification Authority、認証局)と呼ばれる機関に委ねている。

証明書所有者(Subscriber)

証明書を必要とする安全なサービスを希望している主体(人や会社)を証明書所有者(Subscriber)と呼ぶ。

RA(登録局:Registration authority)

RAの仕事は、証明書を発行する前に必要になる本人性の検証をすることである。実際にはCAの多くがRAの役割を果たす。

CA(認証局:Certification authority)

CAは証明書を発行する役割がある。また証明書の失効についての最新情報をオンラインで提供している。

証明書利用者(Relying party)

証明書を実際に使うのが証明書利用者であり、厳密に言えばWebブラウザのプログラムやOSになる。その際にプログラムやOSでは、Root Trust Storeと呼ばれる、いくつかのCAから発行された信頼する証明書を格納されているものを利用する。

証明書

証明書はディジタル署名であり、その中には公開鍵や公開鍵に紐付けられた主体に関する情報、証明書を発行した主体のディジタル署名が含まれている。

Version(バージョン)

証明書にはバージョン1,2,3があり、それぞれ0,1,2の値にエンコードされている。現在ほとんどの証明書はバージョン3になっている。

Serial Number(シリアル番号)

証明書を一意に識別するためにシリアル番号がある。20ビットのエントロピーを有する予測不能な値になっている。

Signature Algorithm(署名アルゴリズム)

証明書の署名に使われているアルゴリズムを示すフィールドのこと。

Issuer(発行者)

証明書を発行した主体の識別名が格納されている。

Validity(有効性)

証明書の有効期限が格納されており、開始の日付と終了の日付の2つで表される。

Subject(主体者)

証明書の発行を受けた者の公開鍵に紐付けられた団体の識別名が格納されている。自己署名証明書の場合は、SubjectとIssuerが同一になっている。現在ではSubjectは使われておらず、代わりにSAN(Subject Alternative Name)という拡張が使われている。

Public key(公開鍵)

公開鍵が格納されている。

証明書の拡張

証明書のフォーマットに柔軟性を持たせるため、バージョン3から拡張ができるようになった。それぞれに拡張子の重要性があり、criticalと設定されている拡張は必ず認識して処理しなければならない。もし処理dけいない場合には証明書ごと破棄する。

Subject Alternative Name(主体者の別名)

SAN拡張は、Subjectフィールドに代わって、DNS名やIPアドレスやURIによって示される複数の主体を公開鍵に結び付けられるようにする。

証明書チェーン

証明書の検証は、信頼の起点となるルートへ連なる証明書チェーンを準備しなければならない。下位のCAはルートCAと違い、通常はオンラインの自動化されたシステムとなっている。そのため複数の下位CA間で運用を分割することで、攻撃のリスクを分散することができる。

CA

CAになるためには、PKIおよびCAについての深い専門知識が必要であり、また法令を遵守するなどの様々な監査が必要になる。2015年にLet's Encryptという無償で証明書を発行できるCAが登場してから、利益目的によるCAの規模は小さくなっている。

証明書のライフサイクル

証明書のライフサイクルは、証明書所有者がCSR(Certificate Signing Request)を用意し、CAに送信することで始まる。CSRの用途は、関連する公開鍵を格納すること、対応する秘密鍵を持っていることを示すことになる。

続いてCAは証明書の検証を行うが、証明書の種類によって異なる。DV証明書の発行は完全に自動化されているため数時間もあれば検証できるが、EV証明書の発行には数日から数週間かかる場合もある。

DV証明書(Domain validation)

ドメイン名を管轄していることの証明に基づいて発行されるのがDV証明書である。ほとんどの場合は「申請承認用メールアドレス」宛に確認のメールが送られるという検証になっている。

OV証明書(Organization validation)

サイトを運営する組織が実在していることの証明に基づいて発行されるのがOV証明書である。

EV証明書(Extended validation)

EV証明書はOV証明書に欠けていた一貫性を解消すべく導入され、検証手順が詳細に文書化されている。このEV証明書は非常に厳格な本人性の検証が要求される。

弱点

インターネットPKIには多くの弱点がある。例としては、CAは許可なくどんなドメイン名の証明書でも発行できるため、営利目的であるCAの手抜きや過失から守る手段がないという点である。またDV証明書は電子メールによる検証がほとんどであるため、ドメイン名の乗っ取りやメールボックスへの侵入によって、偽のDV証明書を簡単に手に入れることができる。

さらに証明書の検証を完全に端折っているライブラリやアプリケーションは数多くある。ブラウザも不正な証明書に遭遇しても回避可能な警告を提示するだけであり、これではセキュリティの意図が台無しになっている。現在はHSTS(HTTP Strict Transport)と呼ばれる新しい標準が開発されており、対応するブラウザに対して警告ではなくエラーを表示することが可能になる。

ルートCA証明書の鍵の危殆化

最も確実なPKIに対する攻撃方法はルートCA証明書を直接狙うことである。2013年、1024ビットの公開鍵は100万米ドルのマシンを使って1年で破れることが発表された。そのため資金力がある機関にはいつでも破られるということを認識する必要がある。

改善

PKIを改善するためのプロトコルは過去数年間にたくさん登場した。しかしそのほとんどは破られ、現在生き残っているのはCT(Certificate Transparency)というものである。CTは、発行する証明書を公開の証明書ログに送り、送ったことの暗号学的な証明を手に入れる。これによりドメイン所有者は、自分のドメインに発行される証明書を監視することができる。


{ "name": "hareku", "job": "Software Engineer" }