mtkw.dev

SSL/TLSの概要に関する理解を整理

これは何

HTTPS(HTTP over SSL/TLS)における通信は安全だと言われています。なぜ安全なのかについて大まかな理解の整理を行いました。

おすすめ書籍

SSL/TLSとは

  • 真正性
    • 通信先のサーバーが本当に意図したサーバーであること
  • 秘匿性
    • 通信内容を第三者に除き見られないこと
  • 完全性
    • 通信内容を第三者に書き換えられないこと(改竄防止)

の3つを担保するためのプロトコル。

各目的を実現する技術

真正性/秘匿性/完全性を担保するために行われる技術を整理する

真正性のための技術

デジタル署名+CA(Certificate Authority, 認証局)によってサーバーの真正性を担保する。 真正性の担保には公開鍵基盤(PKI)の仕組みで実現する。

公開鍵暗号(公開鍵基盤)とは

公開鍵と秘密鍵の計算の一方向性を利用したもの。例: RSA/楕円曲線

例えばRSAであれば素因数分解の計算の難しさをベースに作られている。現在はRSAよりも楕円曲線のアルゴリズムが利用されている。

公開鍵暗号では暗号化と署名を行うことができる。

  • 暗号化
    • 公開鍵で暗号化
    • 秘密鍵で復元
  • 署名
    • 秘密鍵で署名
    • 公開鍵で検証
RSAの暗号計算式
c = m^e mod n
m = c^d mod n

c...暗号文
m...平文
e...公開鍵指数
d...秘密鍵指数
n...p x q(素因数分解の難しさからpとqがバレない前提)
φ(n) = (p - 1)(q - 1)
e × d ≡ 1 mod φ(n)
RSAの署名計算式
s = h(m)^d mod n
h(m) = s^e mod n

s...署名(signature)
m...元データ
h(m)...メッセージのハッシュ(例:SHA-256)
e...公開鍵指数
d...秘密鍵指数
n...p × q(p, qは素数)
φ(n) = (p - 1)(q - 1)
e × d ≡ 1 mod φ(n)

デジタル署名とは

デジタル署名とは公開鍵暗号技術をベースに成り立っている。

デジタル署名により

  • その証明書が改竄されていないこと
  • その証明書がCAによって発行されていること
  • (CAを信頼する場合)信頼の連鎖により、サーバーの真正性を担保できる
証明書 =
  {
    身元情報(example.com など)
    公開鍵
    有効期限
    発行者(CA)
    その他いろいろ
  } <- 証明書本体
  +
  CAのデジタル署名(signature)

例:公開鍵
Subject Public Key Info:
  Algorithm: rsaEncryption
  Public Key:
    Modulus (2048 bit):
      00:c3:af:...:9b  ← 長いバイト列
    Exponent: 65537

例:CAデジタル署名
Signature:
  30:45:02:21:00:...:ff    

上記内容をCAが発行する。サーバーは証明書の内容を”平文”でクライアントに送付する。クライアントは証明書を検証し真正性を検証する。

PKIにおける署名の検証とは

前述での署名(signature)が正しいことをクライアント側で検証する。検証プロセスを理解するには署名の式と見比べれば理解しやすい。

CA側
① hash = SHA256(tbsCertificate)
② signature = hash^d mod n   ← 秘密鍵(d)

クライアント側
① hash1 = SHA256(tbsCertificate)
② hash2 = signature^e mod n  ← 公開鍵(e)
③ hash1 == hash2 ?

CA②でsignatureとはハッシュを秘密鍵で署名したものだとわかる。

つまり、クライアント②で公開鍵とsignatureから証明書本体のハッシュと思われる値(hash2)を取得できる。

クライアント側で証明書本体のハッシュを計算し、一致すれば完全性を検証できる。

サーバー証明書の発行

以下のようなサーバー証明書はどのように作成するのだろうか?

証明書 =
  {
    身元情報(example.com など)
    公開鍵
    有効期限
    発行者(CA)
    その他いろいろ
  } <- 証明書本体
  +
  CAのデジタル署名(signature)

以下で行うことができる。

  1. サーバーは秘密鍵と公開鍵のペアを作成する。そしてCSR(証明書署名要求)を作成
  2. サーバーはドメイン所有の証明するための対応を行う必要がある(HTTP-01 / DNS-01)
  3. CAはCSRを受け取り証明書を作成しそれに署名する

誰でも任意のサービスのCSR証明書を作ることができてしまうため、CAはそのCSRの提出者が本当にそのドメインの所有者であるかを検証する必要がある。その検証プロトコルをACME(Automated Certificate Management Environment)という。HTTP-01であればhttp://<YOUR_DOMAIN>/.well-known/acme-challenge/にファイルを配置することで、CSR提出者がドメイン所有者であることを検証する。

このようなACMEに従ったサーバー証明書の作成とCAへの提出はツールで自動化されている。Certbotというクライアントツールをサーバー管理者がサーバー内で実行すると、CSRの発行からHTTP-01など任意の対応、CAへCSRの提出を自動で行ってくれる。デフォルトではLet's Encryptが送信先のCAとなっている。

信頼の連鎖とは

CAという第三者によって署名されたサーバー証明書をサーバーはクライアントに送付し、クライアントはそれを検証することで、そのサーバーが第三者によって認められたサーバーであることが判定できた。しかしそのCAが悪意のある第三者であった場合、その前提が崩れる。

CAが信頼できるCAだと別のCAが認めること(信頼のチェーン)で、CAの安全性を保証する。

  • サーバー証明書は中間CAによって署名される
  • 中間CAはさらに上位のCAによって署名される
  • 最上位のルートCAはOSやブラウザに事前にインストールされている

クライアントはこのCAの署名を辿って検証することで最終的に端末に事前インストールされたCAに辿り着くことでそのサーバー証明書を署名したCAの安全性を確認することができる。

ルートCAはGoogleやAppleなどではなく、それらのOSやブラウザに信頼された認証局である。

OSやブラウザベンダ(Apple, Google, Microsoftなど)が、 どのルートCAを信頼するかを決定し、あらかじめ端末に組み込んでいる。

  • ISRG Root X1
  • DigiCert Global Root G2
  • GlobalSign Root CA
  • Entrust Root Certification Authority
  • Baltimore CyberTrust Root

最強のルートCAが1つあるわけではなく複数のルートCAが存在しており、証明書を辿るとどれか行き着く。Let's Encryptの場合はISRG Root X1がルートCAとなる。

開発環境でHttps接続するために

自前CAを作成し秘密鍵と公開鍵を作成する。自前CAとCSRからサーバー証明書を作成する。端末のルートCAに自前CAをインストールすることでサーバー証明書を信頼できるようになり、HTTPS通信を構築できる。

mkCertというツールはローカルCAとして秘密鍵で署名したサーバー証明書の発行が可能。またローカルCAを端末にインストールまで行うことが可能。.pemというファイルが「証明書や鍵を保存するためのファイル形式」である。

秘匿性のための技術

共通鍵暗号技術で秘匿性を担保する。

共通鍵暗号では安全に鍵を共有するかという”鍵交換”の問題と、その後の暗号化アルゴリズムが重要になる。

鍵交換アルゴリズム

TLSではECDHE(Elliptic Curve Diffie-Hellman Ephemeral)を用いて鍵交換を行う。

クライアントとサーバーはそれぞれ一時的な鍵ペアを生成し、 それらを用いて安全に共通鍵(セッション鍵)を生成する。

このとき秘密鍵そのものは通信されないため、第三者に共通鍵を知られることはない。

また、ECDHEでは毎回異なる鍵が生成されるため、 過去の通信が後から解読されない(前方秘匿性: Perfect Forward Secrecy)という特徴がある。

2013年のEdward Snowdenにより政府が通信内容を大量に保有している事実が明らかになった。「現在は安全でも将来、復号される危険性」に気づいたエンジニアが、各セッションで鍵を入れ替えることで過去の通信は解読できないようにする重要性に気づき導入が広まった。

共通鍵暗号

鍵交換によって生成されたセッション鍵を用いて、 通信内容の暗号化を行う。

主に以下のアルゴリズムが利用される。

  • AES-GCM
  • ChaCha20-Poly1305

これらは高速に動作し、大量のデータを効率よく暗号化できる。

完全性のための技術

TLSでは通信内容の改ざんを防ぐために、 認証付き暗号(AEAD: Authenticated Encryption with Associated Data)を利用する。

代表例としてAES-GCMやChaCha20-Poly1305があり、 これらは暗号化と同時に認証タグ(Authentication Tag)を生成する。

受信側は以下を行う。

  1. データを復号
  2. 認証タグを検証

認証タグが一致しない場合、その通信は改ざんされたと判断され破棄される。

これにより通信内容の完全性が担保される。

まとめ

  • SSL/TLSは以下を担保する
    • 真正性
      • 通信先のサーバーが本当に意図したサーバーであること
      • 公開鍵暗号基盤の署名/検証と、CAの信頼の連鎖により、サーバー証明書の真正性を保証する
    • 秘匿性
      • 通信内容を第三者に除き見られないこと
      • AES-GCM / ChaCha20-Poly1305が代表的なアルゴリズム
      • 鍵交換(ECDHE)により各セッションで鍵を交換するため前方秘匿性が実現されている
    • 完全性
      • 通信内容を第三者に書き換えられないこと(改竄防止)
      • 認証タグにより改竄を検知する