セキュリティ、TLS

  • 安全確保、機密保持

  • バグに起因

  • 通信が絡むとデータを守るべき箇所が増える

  • ユーザとしてのセキュリティ(使っているパソコン + α)→開発者としてのセキュリティ(サーバ、クライアント、通信路)

通信における危険性

一般に、通信におけるセキュリティ上の危険には、次の3つが考えられる。

  • 盗聴:通信路を流れるデータを第三者が盗み見る

  • 改ざん:通信路を流れるデータを第三者が不正に書き換える

  • なりすまし:第三者が正規の通信相手に成り代わり通信を行い、不正な行為を行う

インターネットにおける通信では、これらのセキュリティ上の危険に対し、公開鍵基盤(Public Key Infrastructure, PKI)という公開鍵暗号方式を基礎とする解決策が広く用いられている。特にWebでは、PKIを利用したセキュアな通信方式であるTLS(Transport Layer Security)が広く用いられる。TLSはトランスポート層(TCP, UDP)とアプリケーション層の間に置かれるプロトコルであり、Web(HTTP)だけでなく、FTP, LDAP, TELNETなどのアプリケーション層プロトコルでも利用できる。

特に、TLS上で実現されるHTTP通信プロトコルをHTTPSと呼ぶ。HTTPSはデフォルトでは443番のポートを用いる。

暗号化技術

TLSの説明をする前に、技術基盤となる暗号化について簡単に解説しておこう。

エンコードと暗号化

データに対し、後で元に戻せるような変換を施すことを エンコード (符号化, encode)という。エンコードされたデータを元に戻すことを デコード (decode)という。ここまでに登場したMIMEエンコーディング、BASE64エンコーディング、URLエンコーディングなどはエンコードの例である。ただし、セキュリティの観点では、一般にエンコードされたデータは誰でもデコードすることができるため、セキュリティ上の危険への対策にはなっていない。

エンコードの特殊な場合として、通信の当事者間でのみ共有される秘密の情報を用いなければデコードできない、というものを考えることができる。このようなエンコードを 暗号化 (encrypt)、暗号化されたデータを復元することを 復号 (decrypt)という。また、暗号化および復号において用いられる、当事者間でのみ共有される秘密の情報を (key)という。

共通鍵暗号方式

暗号化の方式で最も簡単なのは、暗号化と復号とで同じ鍵を用いる方式である。これを 共通鍵暗号方式 (symmetric key cryptography)という。共通鍵暗号方式では、通信の当事者間で同じ鍵( 共通鍵 , symmetric key)を共有する。共通鍵暗号によるデータの暗号化・復号の概略は次のようになる。

  1. あらかじめ生成された共通鍵KKを、何らかの方法で送り手と受け手とで共有しておく。

  2. 送り手はKKを用いて送信したいデータDDを暗号化し(D=encrypt(D,K)D' = {encrypt}(D, K))、暗号化後のデータDD'を受け手に送信する。

  3. 受け手はKKを用いてDD'を復号し(D=decrypt(D,K)D = decrypt(D', K))、元のデータDDを得る。

公開鍵暗号方式

PKIにおいて重要となるもう一つの暗号化方式が 公開鍵暗号方式 (public key cryptography)である。公開鍵暗号方式は、共通鍵暗号方式に比べ計算コストが高いが、後述するように、共通鍵暗号方式での問題点であった「鍵の共有」について解決策を与えるとともに、デジタルデータへの署名(デジタル署名)という別の用途にも解決策を与えている。

公開鍵暗号方式では 秘密鍵 (private key)と 公開鍵 (public key)という2本の鍵を用いる。これらは常に対として用いられ、かつ、次に示す重要な性質がある。

  • 秘密鍵SKSK で暗号化されたデータは公開鍵PKPKでしか復号できない。(D=encrypt(D,SK)D' = encrypt(D, SK) の時 D=decrypt(D,PK)D = decrypt(D', PK))

  • 公開鍵PKPKで暗号化されたデータは秘密鍵SKSKでしか復号できない。(D=encrypt(D,PK)D' = encrypt(D, PK) の時 D=decrypt(D,SK)D = decrypt(D', SK))

後述するように、TLSにおいては、秘密鍵は鍵を生成した当事者が誰にも(もちろん他の当事者にも)知られないよう厳重に保管し、一方公開鍵は誰でも(通信の当事者以外の人でも)利用できるように公開する、という使い方をする。

暗号学的ハッシュ関数

暗号とは異なるが、PKIにおいて重要な役割を果たす暗号学的ハッシュ関数 (cryptographic hash function)というものを紹介しておこう。これは、任意のデータを与えると固定長のビット列を出力する関数(H=hash(D)H = hash(D))で、かつ次のような性質を持つ。

  • 出力結果HHから元のデータDDを求めることは極めて困難(事実上不可能)である。

  • 同じ出力を得るような2つの異なる入力を求めることは極めて困難(事実上不可能)である。(hash(D1)=hash(D2),D1D2hash(D_1) = hash(D_2), D_1 \neq D_2 となるD1,D2D1, D2は事実上求められない) つまり、D1D2D_1 \neq D_2hash(D1)hash(D2)hash(D_1) \neq hash(D_2) は事実上同値であると考えてよい。

HHは、データDDのある種の要約であると考えることができる。この意味で、HHダイジェスト (digest)と呼ぶ。

TLS

では、盗聴・改ざん・なりすましへの対策の観点から、TLSの概要を説明することにしよう。なお、以下の説明では、理解を助けるために、各段階ではやや技術的に不正確な記述をあえて行っている場合がある。

盗聴への対策

まず盗聴への対策である。これは、共通鍵暗号方式によってデータを暗号化すれば良い。

ただし、共通鍵暗号方式には、共通鍵の共有を安全に行わなければならないという大きな問題が残っている。TLSでは、公開鍵暗号方式やDiffie-Helman鍵共有を利用している。公開鍵暗号方式による鍵共有は、大まかには次のようになる。

  1. Webサーバ server 上であらかじめ公開鍵PKservPK_{serv}と秘密鍵SKservSK_{serv}を生成し、PKservPK_{serv}を公開しておく。一方、SKservSK_{serv}はサーバ外部からアクセスできないようにしておく。

  2. Webクライアントclientは共通鍵KKを生成し、次にPKservPK_{serv}をサーバから取得し(ServerCertificateメッセージ)、PKservPK_{serv}KKを暗号化する(D=encrypt(K,PKserv)D = encrypt(K, PK_{serv}))。暗号化した結果DDserverに送信する。

  3. serverDDを受け取り、自身の秘密鍵SKservSK_{serv}DDを復号してKKをとりだす。(K=decrypt(D,SKserv)K = decrypt(D, SK_{serv}))

公開鍵暗号方式の性質により、D=encrypt(K,PKserv)D = encrypt(K, PK_{serv})の復号はSKservSK_{serv}が必要であり、(WebサーバでSKservSK_{serv}が厳格に保管されている限り)盗聴される心配はない。

改ざんへの対策

改ざんへの対策には暗号学的ハッシュ関数が用いられる。ただし、通常の暗号学的ハッシュ関数ではなく、送信したいデータと共通鍵を用いて計算を行うため、メッセージ認証符号(Message Authentication Code, MAC)と呼ばれている。

  1. 送信側で、送信したいデータDDと共通鍵KKからMAC値H=hash(D,K)H=hash(D, K)を計算し、DDHHをまとめて共通鍵KKで暗号化(D=encrypt({D,H},K)D' = encrypt(\{D, H\}, K))、DD'を送信する。

  2. 受信側ではDD'からDDHHを取り出し({D,H}=decrypt(D,K)\{D, H\} = decrypt(D', K))、DDHHからMAC値を計算する(H=hash(D,K)H' = hash(D, K))。暗号学的ハッシュ関数の性質から、H=HH = H'なら通信路上での改ざんはないと保証することができる。

実際にはDDHHだけでなく、送信側と受信側しか知らないパラメータを含めて暗号化するなどの対策が行われるため、DDHHがともに改ざんされたとしても、改ざんを検出することができる。

なりすましへの対策

なりすましへの対策は、Webサーバの公開鍵PKservPK_{serv}が正当なものであることを検証することであり、公開鍵暗号方式による電子署名が用いられている。

ここで登場するのが認証局(Certificate Authority, CA)である。認証局はすべての通信の当事者が信頼することのできる第三者機関で、PKservPK_{serv}の正当性を示すデジタル公開鍵証明書を発行することが主な役割である。実際には専門業者や政府機関などが認証局となる。

  1. 認証局CAはあらかじめ自身の公開鍵PKCAPK_{CA}と秘密鍵SKCASK_{CA}を用意し、PKCAPK_{CA}を誰でも取得できるように公開しておく。

  2. Webサーバserverを運用する組織は、CAPKservPK_{serv}のデジタル公開鍵証明書の発行を依頼する。

  3. CAPKservPK_{serv}SKCASK_{CA}で暗号化(C=encrypt(PKserv,SKCA)C = encrypt(PK_{serv}, SK_{CA}))し、serverの運用組織に渡す。このCCPKservPK_{serv}のデジタル公開鍵証明書になる。

  4. Webサーバserverでは、PKservPK_{serv}CCをともに公開する。

WebクライアントclientPKservPK_{serv}の他にCCPKCAPK_{CA}をすべて取得し、PKCAPK_{CA}CCの復号を試みる(decrypt(C,PKCA)decrypt(C, PK_{CA}))。復号に成功すれば、PKservPK_{serv}CCを取得した通信相手はCAによって認証を受けた正当なサーバであり、なりすましはされていないと保証される。

ではclientPKCAPK_{CA}の正当性をどうやって検証すればいいのだろうか。実は、PKCAPK_{CA}自体もまた他の認証局によって発行されたデジタル公開鍵証明書により正当性が証明されるのである。このように、多くの認証局が互いに信用関係を持つことで、公開鍵暗号方式での鍵の正当性が保証されている。どのような信用関係を形成するかは信用モデルと呼ばれ、多数のモデルが使われているが、Webでは木状の階層構造に信用関係を形成し、かつWebブラウザに信用できるいくつかの認証局の公開鍵をあらかじめ内包しておく、という解決策を取っている。

暗号アルゴリズムの決定

このようにTLSでは鍵交換、共通鍵による暗号化、暗号学的ハッシュ関数、電子署名に暗号技術が用いられており、具体的なアルゴリズムは多数提案されている。そこでTLSにはこれらの暗号アルゴリズムの組み合わせ(暗号スイート, Cipher Suites)がいくつか定められており、TLSでのハンドシェイクの最初にどの暗号スイートを使うか、通信の当事者間で合意を取る。

  1. Webクライアントclientは、自身が利用できる暗号スイートの一覧をWebサーバserverに送信する。(ClientHelloメッセージ)

  2. serverは、clientから送られてきた暗号スイートの中から一つを選び、clientに送信する。(ServerHelloメッセージ)

このやり取りでは、暗号スイート以外にも、使用するTLSのバージョンや共通鍵を生成するのに必要な乱数なども交換され、clientserverで共有される。

ところでHTTP/2では、WebクライアントとWebサーバがともにHTTP/2を理解できる場合にのみHTTP/2を用い、それ以外の場合にはHTTP/1.1を用いる。つまり、HTTP/1.1でハンドシェイクを開始し、双方がHTTP/2を理解できる場合にのみHTTP/2による通信に変更する(プロトコルアップグレード)。HTTP/2では、その実装の一つとして、ClientHelloメッセージ及びServerHelloメッセージの拡張であるALPN(Application Layer Protocol Negotiation)を用いる方法を定めている。ALPNでは、TLSのClientHelloメッセージの中に、Webクライアントが使用できるHTTPプロトコルの一覧も含め、Webサーバがその中から一つを決定して、ServerHelloメッセージによってクライアントに通知する。