Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

SSL/TLSの基礎と最新動向

47,321 views

Published on

SSL/TLSの基礎と最新動向 セキュリティキャンプ2015

Published in: Technology

SSL/TLSの基礎と最新動向

  1. 1. SSL/TLSの基礎と最新動向 セキュリティキャンプ 2015 2015年8月12日 IIJ 大津 繁樹 更新版資料の置場 http://goo.gl/cX1M17 Github Repo: https://goo.gl/vRLzrj
  2. 2. 自己紹介 • 大津 繁樹 • 株式会社 インターネットイニシアティブ • プロダクト本部 アプリケーション開発部サービス開発2課 • NodeJS Technical Committee メンバー • (主にTLS/CRYPTO/OpenSSLバインディングを担当) • IETF httpbis WG で HTTP/2相互接続試験等仕様策定に参画。 • ブログ: http://d.hatena.ne.jp/jovi0608/
  3. 3. はじめに • TLS(Transport Layer Security)の仕組みについて学んでいただき ます。 • 後述するようTLSは、様々なセキュリティの要素技術から成り 立っており、その一つ一つが難解で深い技術要素です。 • 残念ながら4時間もの時間があってもその全てを完全に理解す ることは容易ではありません。
  4. 4. 本講義の目的 • TLSの本質は、要素技術をどう組み合わせてどういう手順でセ キュアな通信を確立するかというところにあります。そのため、 本講義の目的は、TLS技術の基礎 「TLSハンドシェイクの仕組み」 を理解していただくことです • 聞いているだけの理解より、実際に手を動かしての体験する方 を重視して進めます。 • 課題内容は空白にしています。講義当日にお知らせします。
  5. 5. 本講義の内容 • TLSの概要 • TLSを理解する準備 • TLSの話 • まずは TLS_RSA_WITH_AES_128_GCM_SHA256 の時から • Perfect Forward Secrecy • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256を使う • 最新情報 TLS1.3とはどういうものか? 概要説明
  6. 6. まずやってみる モジュールのインストール $npm install seccamp2015-data-reader seccamp2015-tls Simple TLS Client (simple_tls_client.js)の取得 $git clone https://github.com/shigeki/SecCamp2015-TLS $cd SecCamp2015-TLS $node simple_tls_client.js キーボードを打ってみよう (注:エラー処理やサニタイジングが十分でないのであくまでテスト用で利用すること)
  7. 7. TLSの概要
  8. 8. インターネットの脅威 盗聴 パスワードやク レジットカード 番号を盗み見
  9. 9. インターネットの脅威 改ざん 通信途中でデー タを書き換え
  10. 10. インターネットの脅威 なりすまし ユーザになりす まして通信を行 う
  11. 11. インターネットの脅威 否認 そんな通信してま せんと否認する
  12. 12. インターネットの脅威から守るセキュリ ティ対策 盗聴 改ざん 成りす まし 否認 暗号化 完全性 チェック 認証 署名
  13. 13. 各レイヤーにおけるセキュリティ通信 WPA IPsec TLS,DTLS,SSH S/MIME, PGP 無線LAN IP TCP, UDP データ
  14. 14. TLSの目的 • TLSプロトコルの最重要なゴールは、通信する2つのアプリケー ションの間でプライバシーとデータの完全性を提供することです。 RFC5246: The Transport Layer Security (TLS) Protocol Version 1.2 1. Introduction The primary goal of the TLS protocol is to provide privacy and data integrity between two communicating applications. アプリ アプリ 完全性 プライバシー
  15. 15. TLSの簡単な歴史 • SSL 1.0未発表 • 1994年 SSL 2.0 • 1995年 SSL 3.0 • 1996年 IETF TLS WGスタート • 1999年 TLS 1.0 • 2006年 TLS 1.1 • 2008年 TLS 1.2 • 2013年 TLS 1.3検討スタート SSLは、旧ネットスケー プ社の私的プロトコル TLSと名前を変えて標準化 SSL3.0と基本設計は大き く変えず、内部バージョ ンは TLS1.0 =SSL 3.1 現在の利用推奨 様々な拡張仕 様の追加
  16. 16. TLSを理解する準備
  17. 17. TLSの要素技術 X509 証明書 PKI 対称 暗号 暗号 モード 公開鍵 暗号 デジタ ル署名 メッセージ認証 乱数 生成 TLS 鍵交換 一方向ハッシュ TLSプロトコルは、これらの要素技術を組み合わせてアプリ間のセキュ ア通信を確立する手順を決める
  18. 18. TLS要素技術の依存性 X509 証明書 PKI 対称 暗号 暗号 モード 公開鍵 暗号 デジタ ル署名 メッセージ認証 乱数 生成 鍵交換 一方向ハッシュ 本来はこの一つ一つをきちんと理解してもらうのが必要
  19. 19. TLS要素技術の依存性 X509 証明書 PKI 対称 暗号 暗号 モード 公開鍵 暗号 デジタ ル署名 メッセージ認証 乱数 生成 鍵交換 一方向ハッシュ GCM AES ECDHE RSA SHA256 HMAC 本日の講義で扱う技術 説明は概要だけですが、演習で実際の動作を手を動かして体験してもらいます。
  20. 20. 要素技術とTLS CipherSuites TLS_RSA_WITH_AES_128_GCM_SHA256 = {0x00,0x9C} TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256= {0xC0,0x2F}; 対称 暗号 暗号 モード デジタ ル署名 メッセージ認証 (ハッシュ) 鍵交換TLS _ _ _WITH_ _ 鍵長 _ _ 鍵交換・デジタル署名にRSA 対称暗号に128bit鍵長のAES 暗号モードにGCM ハッシュにSHA256 番号として 0x00,0x9Cを割り当て 鍵交換にECDHE デジタル署名にRSA 対称暗号に128bit鍵長のAES 暗号モードにGCM ハッシュにSHA256 番号として 0xC0,0x2Fを割り当て
  21. 21. 乱数生成 利用用途: • 暗号鍵(対称暗号:秘密鍵、公開鍵暗号:鍵ペア)の生成 • 暗号モードの初期ベクトルやNonce(*)の生成 • MAC(メッセージ認証)用鍵 (* Nonce(number used once)一度だけ使い捨て用に使われる数字 求められる機能 無作為性: 偏りがなく等しい数である。 予測不可能性: 次の乱数が予想できない。 制限負可能性: 同じ乱数列を再現できない。
  22. 22. 乱数生成 • 実際の利用は、疑似乱数生成。seedが必要。 • OpenSSLでは、seedはLinuxの/dev/urandomを利用。Windows ではOSのAPIのCryptGenRandomだけでなく画面スクリーンの ビットマップハッシュも利用。 脆弱性: • CVE-2008-0166: DebianやUbuntuのOpenSSLに予測可能な乱 数を生成してしまう脆弱性 • SSH公開鍵にブルートフォース攻撃
  23. 23. 対称暗号 暗号文 平文 共通鍵 共通鍵 平文 ストリーム暗号:データを逐次暗号化(RC4, Chacha20) ブロック暗号:データをブロック毎に暗号化(DES, AES) 幾つかの暗号では既に危殆化: DES: 2005年 NIST FPS46-3規格の廃止(2030年までは許容) RC4: RFC7455: Prohibiting RC4 Cipher Suites 暗号化 復号化
  24. 24. 対称暗号 AES • 1997年よりプロジェクト開始、2000年選定、2001年仕様発行 • ブロックサイズ 128bit • 鍵長: 128bits, 192bits, 256bits の3種類 • Intel/AMDのCPUでハードウェア処理のサポート AES-NI
  25. 25. 暗号モード • ブロック暗号は同じデータを同じ鍵で暗号化すると毎回同一の 暗号文になる。 • ブロック長より長いデータを暗号化する場合に暗号モードを利 用して繰り返しを避ける。 • CBC:「(平文 XOR ベクトル) を暗号化」を続ける • CTR: 「カウンターを暗号化 XOR 平文」を続ける 実際にTLSで利用するには改ざん検知のためのMAC(メッセージ認証)との組み合わせる(AEAD)。 これまで の主流 これからの主流 に(GCM後述)
  26. 26. AEAD(認証付き暗号) 暗号化しないけど改ざ ん防止が必要なデータ (ヘッダ等) 暗号化する平文 AEAD 暗号化 暗号文 認証タグ 共通鍵 初期ベクトル
  27. 27. AEAD(認証付き暗号) 平文 AEAD 復号化 改ざんチェック 暗号化しないけど改ざ ん防止が必要なデータ (ヘッダ等) 暗号文 認証タグ 共通鍵 初期ベクトル
  28. 28. GCM • GCM (Galois Counter Mode: ガロアカウンターモード) • CTRとGHASHを組み合わせたAEAD • ハードウェア処理で高速化が可能 • AESと組み合わせて AES-GCMとして利用
  29. 29. 一方向ハッシュ データ 一方向 ハッシュ関数 ハッシュ値 ハッシュ値を比較することでデータの改ざんをチェックすることができる。
  30. 30. 一方向ハッシュ • md5 • SHA-1 • SHA-2(SHA-256など6種) • SHA-3(SHA3-256など6種) 2018年ぐらいには現実的なコストで 衝突データを探せる見込み(*2) 既に現実的な攻撃手法が存在 (*1) (*2) Cryptanalysis of SHA-1 https://www.schneier.com/blog/archives/2005/02/cryptanalysis_o.html (*1) how to Break MD5 and Other Hash Functions http://merlot.usc.edu/csac-f06/papers/Wang05a.pdf 8/5にNISTより正式公開
  31. 31. メッセージ認証(HMAC) • 事前に共通鍵を共有 • 共通鍵とデータを組み合わせたハッシュ値を作成 • データの完全性とハッシュ作成者を認証する データ 一方向 ハッシュ関数 ハッシュ値 共通鍵
  32. 32. 公開鍵暗号 512bit RSAの危険性 FREAK https://freakattack.com/ • 解を求めるのが困難な数学的問題を利用して暗号を生成。 • 公開鍵と秘密鍵のペアを生成。公開鍵はさらして大丈夫。 • 公開鍵で暗号化し秘密鍵で復号化。 • RSA • ECC(楕円曲線暗号) 公開鍵 秘密鍵 暗号化 復号化
  33. 33. 鍵交換 • 2者間で安全に鍵を共有する仕組み • 互いに公開鍵を交換しあい、共有鍵を生成する。 • 通信経路上で共有鍵のやり取りがない • DH (Diffie-Hellman) • ECDH(楕円曲線DH) 512bit DH Logjam https://weakdh.org/
  34. 34. デジタル署名 • データの完全性のチェックが可能となる。 • データの送信元の認証が可能となる。 • 公開鍵の信頼性の範囲で否認防止が可能となる。 • RSA • DSA,ECDSA 公開鍵秘密鍵 データ+デジタル署名 データハッシュ値 を暗号化しデジタ ル署名を生成 デジタル署名を復号化。 データハッシュ値と比較し 検証する
  35. 35. X509証明書(Certificate) • 公開鍵と所有者・発行者やその他属性情報をデジタル署名した データ • 元々は電子ディレクトリサービス仕様(X500)の一部 • 認証局(CA)が所有者の実体を確認して証明書を発行する(PKI)
  36. 36. X509証明書(Certificate)
  37. 37. 演習: sudo npm install -g seccamp2015-crypto-workshopper • 乱数生成 • AES-GCM • 公開鍵暗号 • 一方向ハッシュ • 鍵交換 • メッセージ認証 • デジタル署名 • X509証明書 (時間がなさそうなので取りやめました)
  38. 38. TLSの話 まずは TLS_RSA_WITH_AES_128_GCM_SHA256 の時から 注:複雑さを避けるためクライアント認証機能は説明しません
  39. 39. TLSデータ表現の仕方 (構造体,メンバー) struct { uint8 major; uint8 minor; } ProtocolVersion; 0 1 majaor minor ProtocolVersion version = { 3, 3 }; /* TLS v1.2*/ 0 1 0x03 0x03 8bit符号なし整数 (2バイト) 構造体と同じ 構造体名
  40. 40. TLSデータ表現の仕方(配列・エンディアン) struct { uint32 gmt_unix_time; opaque random_bytes[28]; } Random; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 gmt_unix_time random_bytes 32bit符号なし整数(4バイト) 1970/1/1 0:00(UTC)からの経過秒数 28バイト長の任意のバイト列 []の中はバイト数を表す。 データを書き込むときは、最上位の バイトデータをインデックスの小さ い方から大きい方への順番で書き込 む (big-endian/network byte order) Mon Jul 20 2015 01:55:29 GMT+0900 (JST) = 1437324929 sec = 0x55abd681 0 1 2 3 55 ab d6 81
  41. 41. TLSデータ表現の仕方 (可変ベクター) opaque SessionID<0..32>; <>は可変ベクター型を表す。 中の数字は、<最少サイズ..最大サイズ> 先頭にサイズを必ず入れ、その後にデータが続く。 先頭のサイズの領域は最大サイズが格納できる量。 左の場合は最大32バイトだから1バイト(255まで表 現可能)分のサイズ領域があればよい。 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 0x20 SessionID(32バイト) 0 1 0x01 SessionID(1バイト) 0 0x00 SessionIDのサイズが0の場合 SessionIDのサイズが1の場合 SessionIDのサイズが32の場合
  42. 42. TLSデータ表現の仕方 (enum) uint8 CipherSuite[2]; enum { null(0), (255) } CompressionMethod; 8bit符号なし整数が 2バイト 0 1 0x00 0x40 CipherSuite TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = { 0x00,0x40 }; CompressionMethodの値は最大255まで(1バイト分) NULLは0に割り当てられています。
  43. 43. TLSデータ表現の仕方 (条件式) struct { ProtocolVersion client_version; Random random; SessionID session_id; CipherSuite cipher_suites<2..2^16-2>; CompressionMethod compression_methods<1..2^8-1>; select (extensions_present) { case false: struct {}; case true: Extension extensions<0..2^16-1>; }; } ClientHello; 条件式 extensionが存在しなければ、空 してれば、0~2^16-1までの可変ベク ターのデータが入る
  44. 44. TLSデータ表現の仕方 (読んでみよう) struct { ExtensionType extension_type; opaque extension_data<0..2^16-1>; } Extension; enum { signature_algorithms(13), (65535) } ExtensionType;
  45. 45. TLSデータ表現の仕方 (読んでみよう) enum { none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), sha512(6), (255) } HashAlgorithm; enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } SignatureAlgorithm; struct { HashAlgorithm hash; SignatureAlgorithm signature; } SignatureAndHashAlgorithm; SignatureAndHashAlgorithm supported_signature_algorithms<2..2^16-2>;
  46. 46. TLSデータ表現の仕方 (読んでみよう) struct { uint8 major; uint8 minor; } ProtocolVersion; enum { change_cipher_spec(20), alert(21), handshake(22), application_data(23), (255) } ContentType; struct { ContentType type; ProtocolVersion version; uint16 length; opaque fragment[TLSPlaintext.length]; } TLSPlaintext;
  47. 47. TLS1.2の構造 I P ヘ ッ ダ T C P ヘ ッ ダ TLS Record Layer (5バイト) タイプ (4種類) (1byte) バージョン (2byte) 長さ (2byte) Handshake (タイプ:0x16) msgタイプ (10種類) 長さ (3バイト長) ハンドシェイクデータ Alert (タイプ:0x15) レベル 理由 ChangeCipherSpec (タイプ:0x14) タイプ Application Data (タイプ:0x17) 暗号化されたデータ msgタイプ ハンドシェイクデータの種類 0x00 HelloRequest 0x01 ClientHello 0x02 ServerHello 0x0b Certificate 0x0c ServerKeyExchange 0x0d CertificateRequest 0x0e ServerHelloDone 0x0f CertificateVerify 0x10 ClientKeyExchange 0x14 Finished TLS Record Layer データに続いて、次 の4種類のTLSデー タのいずれかが続く。 TLS Handshakeは、こ の10種類に分かれる。
  48. 48. TLSハンドシェイクデータの構造 struct { HandshakeType msg_type; uint24 length; select (HandshakeType) { case hello_request: HelloRequest; case client_hello: ClientHello; case server_hello: ServerHello; case certificate: Certificate; case server_key_exchange: ServerKeyExchange; case certificate_request: CertificateRequest; case server_hello_done: ServerHelloDone; case certificate_verify: CertificateVerify; case client_key_exchange: ClientKeyExchange; case finished: Finished; } body; } Handshake; enum { hello_request(0), client_hello(1), server_hello(2), certificate(11), server_key_exchange (12), certificate_request(13), server_hello_done(14), certificate_verify(15), client_key_exchange(16), finished(20) (255) } HandshakeType; Handshake (タイプ:0x16) msgタイプ (10種類) 長さ (3バイト長) ハンドシェイクデータ msgタイプの種 類でそれぞれの 構造を参照する
  49. 49. TLSハンドシェイク まずは TLS_RSA_WITH_AES_128_GCM_SHA256 の時から
  50. 50. TLSハンドシェイク(full handshake) ClientHello ServerHello Certificate ServerHelloDone ClientKeyExchange ChangeCipherSpec Finished ChangeCipherSpec Finished Application Data Application Data (赤文字はハンドシェイク) ClientHelloとServerHello のやり取りで双方が利用 するTLSバージョンや暗 号化方式などを合意する。
  51. 51. TLSハンドシェイク(resumption) ClientHello ServerHello ChangeCipherSpec Finished ChangeCipherSpec Finished Application Data Application Data (赤文字はハンドシェイク) SessionIDによるTLSセッ ションの再開。 鍵交換や証明書送付をス キップ。 今回は演習の対象外です
  52. 52. TLSハンドシェイクの意味 ClientHello/ServerHello/ServerHelloDone TLSのための情報交換 バージョン・乱数・暗号方式・拡張情報 Certificate 公開鍵情報の送付 エンドポイントの認証 ClientKeyExchange/ServerKeyExchange 共有鍵交換 ChangeCipherSpec 暗号開始の合図 Finished ハンドシェイクデータの改ざんチェック
  53. 53. ClientHello struct { ProtocolVersion client_version; Random random; SessionID session_id; CipherSuite cipher_suites<2..2^16-2>; CompressionMethod compression_methods<1..2^8-1>; select (extensions_present) { case false: struct {}; case true: Extension extensions<0..2^16-1>; }; } ClientHello;
  54. 54. ClientHello 項目 要素 サイズ 先頭の長さ情報 client_version uint8 major, uint8 minor 2 N/A random uint32 gmt_unix_time, opaque random_bytes[28] 4 + 28 N/A session_id opaque SessionID <0..32> 1バイト分 cipher_suites uint8 CipherSuite[2] <2..2^16-2> 2バイト分 compression_met hods null(0) <1..2^8-1> 1バイト分 extensions extension_type(65535), extension_data<0..2^16-1> <0..2^16-1> 2バイト分 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 type データ 長 データ type データ 長 データ type データ 長 データ Extension長 Extensionsデータ例
  55. 55. ClientHello Record Layer Handshake (ClientHello) type protocol version length (2byte) msg type length (3byte) client version random session id cipher suite compr ession Extensi on major minor major minor 0x16 0x03 0x01 ?? ?? 0x01 ?? ?? ?? 0x03 0x03 32 byte 可変 可変 可変 可変 Version 0x03,0x00 = SSLv3 0x03,0x01= TLSv1.0 0x03,0x02=TLSv1.1 0x03,0x03=TLSv1.2 クライアントが利用で きる最高のTLSバー ジョンを指定、サーバ がどのバージョンを使 うか選択する
  56. 56. Record Layer Handshake (ClientHello) type protocol version length (2byte) msg type length (3byte) client version random session id cipher suite compression major minor major minor 0x16 0x03 0x01 0x00 0x2D 0x01 0x00 0x00 0x29 0x03 0x03 32 byte All 0x00 0x00 0x00,0x02 0x00,0x9c 0x01 0x00 CipherSuite 指定(1種) TLS1.2用 TLS_RSA_WITH_AES_128_GCM_SHA256:0x00,0x9c 41 byte長45 byte長 最小のClientHello '160301002D' '0100290303' crypto.randomBytes(32).toString('hex') '000002009C0100' 本当はちゃんとし た乱数を入れる + + +
  57. 57. 演習: 最少ClientHelloを作って送る https://gist.github.com/shigeki/d880ae0b4eef3cfd1acc var net = require('net'); var crypto = require('crypto'); var recordheader = '160301002D'; var random = crypto.randomBytes(32).toString('hex'); var handshake = '010000290303' + random + '000002009C0100'; var clienthello = new Buffer(recordheader + handshake, 'hex'); var client = net.connect({host: 'tls.koulayer.com', port: 443}, function() { client.write(clienthello); }); client.on('data', function(c) { // Receive ServerHello console.log(c); });
  58. 58. ServerHello struct { ProtocolVersion server_version; Random random; SessionID session_id; CipherSuite cipher_suite; CompressionMethod compression_method; select (extensions_present) { case false: struct {}; case true: Extension extensions<0..2^16-1>; }; } ServerHello; 複数ではない 複数ではない
  59. 59. ServerHello 項目 要素 サイズ 先頭の長さ情報 server_version uint8 major, uint8 minor 2 N/A random uint32 gmt_unix_time, opaque random_bytes[28] 4 + 28 N/A session_id opaque SessionID <0..32> 1 cipher_suite uint8 CipherSuite[2] 2 N/A compression_met hod null(0) 1 N/A extensions extension_type, extension_data<0..2^16-1> <0..2^16-1> 2バイト分 Record Layer(5bytes) Handshake (ServerHello) type protocol version length (2bytes) msg type length (3byte) server version random 32bytes session id cipher suite 2bytes compression major minor major minor 0x16 0x03 0x03 ? + 4 0x01 ? 0x03 0x03 ? 長さ1byte 0x00,0x9c 長さ2bytes
  60. 60. DataReaderを使う https://github.com/shigeki/seccamp2015-data-reader データを読み込むHelperオブジェクト var DataReader = require('seccamp2015-data-reader').DataReader; var reader = new DataReader(buffer); API • reader.readBytes(n):前回読み込んだ位置からnバイト分のデータをバッファで返す • reader. readVector(floor, ceiling):可変ベクターのデータを読み込み、バッファで返す。(floor:最小値、 ceiling:最大値) • reader. peekBytes(from, n): from個目からto個目までのバッファをコピーして返す • reader. bytesRemaining(): 残っているバイトサイズを返す
  61. 61. 演習: Record Headerを見る function parseRecordHeader(reader) { var type = reader.readBytes(1).readUInt8(0); var version = reader.readBytes(2); var length = reader.readBytes(2).readUIntBE(0, 2); return {type: type, version: version, length: length}; } Record Layer type (1byte) protocol version length (2bytes) major (1byte) minor (1byte)
  62. 62. 演習 ServerHelloを見る https://gist.github.com/shigeki/67c35e12b0834fca3821 function parseServerHello(reader) { var record_header = parseRecordHeader(reader); var type = reader.readBytes(1).readUInt8(0); var length = reader.readBytes(3).readUIntBE(0, 3); var version = reader.readBytes(2); var random = reader.readBytes(32); var session_id = reader.readVector(0, 32); var cipher = reader.readBytes(2); var compression = reader.readBytes(1); return { record_header: record_header, type: type, length: length, version: version, random: random, session_id: session_id, cipher: cipher, compression: compression }; } Handshake (ServerHello) msg type length (3byte) server version random 32bytes session id cipher suite 2bytes compression major minor
  63. 63. Certificate opaque ASN.1Cert<2^24-1>; struct { ASN.1Cert certificate_list<0..2^24-1>; } Certificate; 項目 要素 サイズ certificate_list ASN.1Cert<2^24-1> <0..2^24-1> 最大値のみ 3バイト分 全証明書長 証明書#1長 証明書データ#1 証明書#2長 証明書データ#2 3バイト分 複数の証明書データを送付 最初は必ずサーバ証明書 2つ目以降は中間証明書など
  64. 64. ここから先の演習は状態管理が必要 はじめに使った simple_tls_client.js を使います。 モジュールのインストール $npm install seccamp2015-data-reader seccamp2015-tls Simple TLS Client (simple_tls_client.js)の取得 $git clone https://github.com/shigeki/SecCamp2015-TLS $cd SecCamp2015-TLS $node simple_tls_client.js キーボードを打ってみよう (注:エラー処理やサニタイジングが十分でないのであくまでテスト用で利用すること)
  65. 65. 演習 Certificateを見る https://github.com/shigeki/SecCamp2015-TLS/blob/master/index.js function parseCertificate(reader, state) { if (!checkRecordHeader(reader)) return null; var record_header = parseRecordHeader(reader); storeHandshakeData(reader, record_header.length, state); var type = reader.readBytes(1).readUInt8(0); var length = reader.readBytes(3).readUIntBE(0, 3); var cert_reader = new DataReader(reader.readBytes(length)); var certlist = []; while(cert_reader.bytesRemaining() > 0) { var cert = cert_reader.readVector(0, 1 << 24 - 1); certlist.push(cert); } return { record_header: record_header, type: type, length: length, certlist: certlist }; } 証明書はリストに格納 3バイト分
  66. 66. ServerKeyExchange RSA鍵交換では不要。今の時点じゃスキップします。 ECDHEのところで再度説明します。
  67. 67. ServerHelloDone struct { } ServerHelloDone; handshake type handshake長 0x0e 0x00 0x00 0x00 ServerHelloの終了の合図 ハンドシェイクヘッダのみ
  68. 68. ClientKeyExchange struct { select (KeyExchangeAlgorithm) { case rsa: EncryptedPreMasterSecret; case dhe_dss: case dhe_rsa: case dh_dss: case dh_rsa: case dh_anon: ClientDiffieHellmanPublic; } exchange_keys; } ClientKeyExchange; 鍵交換のアルゴリズム によって異なる RSAによる鍵交換では 暗号化された PreMasterSecretを送る DH/DHEによる鍵交換 ではクライアントの公 開鍵を送る。
  69. 69. ClientKeyExchange (RSA鍵交換の場合) struct { ProtocolVersion client_version; opaque random[46]; } PreMasterSecret; struct { public-key-encrypted PreMasterSecret pre_master_secret; } EncryptedPreMasterSecret; ClientHelloで送付 したバージョン 通常は証明書に記載されているRSA 公開鍵でpre_master_secretを暗号化 エラー処理が脆弱性 がなる場合もある <0..2^16-1>の可変ベクター
  70. 70. ClientKeyExchange (RSA鍵交換の場合) Record Layer(5bytes) Handshake(ClientKeyExchange) type protocol version length (2bytes) msg type length (3byte) Encrypted PreMasterSecret major minor 0x16 0x03 0x03 ? + 4 0x10 ? 長さ2バイト ? PreMasterSecret client version random 46bytes major minor 0x03 0x01
  71. 71. TLSの鍵生成の流れ pre master secret (任意のバイト数:鍵交換による) サーバ・クライアント間の鍵交換方式で生成し、秘密的に共有する master secret (48 bytes) PRF(pre_master_secret, "master secret", client_random+server_random) keyblock (任意のバイト数:利用暗号方式による) PRF(master_secret, "key expansion", server_random+client_random) client_write_MAC server_write_MAC client_write_key server_write_key client_write_IV server_write_IV
  72. 72. PreMasterSecret/MasterSecret • TLSで利用するIV(初期ベクトル)、共有鍵、MAC鍵のデータ元 • MasterSecretは48バイト長。PreMasterSecretの長さは鍵交換方式に依 存する。 • MasterSecretは、PreMasterSecret、ClientRandom、ServerRandom、 固定ラベルから生成する。 • Clinet/ServerRandomは全て丸見え。PreMasterSecretは、必ず死守し て守らないといけない。これが漏えいするとTLSの安全性は全てお じゃん。
  73. 73. 演習:PreMasterSecretの計算 TLS1.2のRSA鍵交換時 function createPreMasterSecretRSAKeyExchange(state) { var pre_master_secret = (ここを作る) return pre_master_secret; }
  74. 74. 演習答え:PreMasterSecretの計算 TLS1.2のRSA鍵交換時(48バイト) function createPreMasterSecretRSAKeyExchange(state) { var version = new Buffer('0303', 'hex'); var pre_master_secret = Buffer.concat([version, crypto.randomBytes(46)]); return pre_master_secret; } ClientHelloで送った Version 2バイト分 残り46バイトは乱 数で発生させる
  75. 75. 演習: ClientKeyExchangeを作る var clientkeyexchange_json = { pre_master_secret: pre_master_secret, pubkey: require('fs').readFileSync(__dirname + '/pubkey.pem') }; var clientkeyexchange = createClientKeyExchange(clientkeyexchange_json, state); function createClientKeyExchange(json, state) { state.handshake.clientkeyexchange_json = json; var public_key = json.pubkey; var pre_master_secret = json.pre_master_secret; var encrypted = crypto.publicEncrypt({ key: public_key, padding: require('constants').RSA_PKCS1_PADDING }, pre_master_secret); var encrypted_pre_master_secret = writeVector(encrypted, 0, 1 << 16 - 1); var handshake = createHandshake(handshake_type.clientkeyexchange, encrypted_pre_master_secret); return createRecord(type.handshake, handshake); }; 公開鍵情報は、本当は Certificate デー タから抽出する。パーサーが必要なの で別ファイルから読み込む 公開鍵で pre_master_secretを暗号化
  76. 76. MasterSecretの計算 その1: P_hash PreMasterSecretのサイズは、鍵交換方式で異なる。 MasterSecretは48バイト必要。 P_hash: データ拡張関数。あるsecretを必要なサイズまで伸長させる。 P_hash(secret, seed) = HMAC_hash(secret, A(1)+seed) + HMAC_hash(secret, A(2)+seed) + …. (必要なサイ ズまで伸長) A(0) = seed; A(i) = HMAC_hash(secret, A(i-1)) +はデータの結合を表す。 HMAC_hashのアルゴリズムは、TLS1.2では SHA256を 使う(それ以前はMD5/SHA-1の組み合わせ)。
  77. 77. 演習: TLS1.2の P_hashを作る var crypto = require('crypto'); var P_hash = require('seccamp2015-tls').P_hash; var algo = 'sha256'; var secret = 'mysecret'; var seed = (new Buffer(32)).fill(0); var size = 48; function MyP_hash(algo, secret, seed, size) { var ret = new Buffer(size); (ここを作る) return ret; } var answer = P_hash(algo, secret, seed, size); var my_answer = MyP_hash(algo, secret, seed, size); console.log(answer); console.log(my_answer); console.log(answer.equals(my_answer));
  78. 78. function MyP_hash(algo, secret, seed, size) { var ret = new Buffer(size); var hmac = crypto.createHmac(algo, secret); hmac.update(seed); var a = hmac.digest(); // A(1) var end = 0; while(size > end) { hmac = crypto.createHmac(algo, secret); hmac.update(Buffer.concat([a, seed])); var b = hmac.digest(); var len = (size - end >= b.length) ? b.length: size - end; b.copy(ret, end, 0, len); end += len; hmac = crypto.createHmac(algo, secret); hmac.update(a); a = hmac.digest(); // A(i+1) } return ret; } 演習: 答え HMAC_hash(secret, A(i)+seed) サイズ分まで結合する 次のA(i)を計算 A(0)はseed A(1)を計算
  79. 79. MasterSecretの計算 その2 PRF(PseudoRandom Function) PRF(secret, label, seed) = P_hash(secret, label + seed) master_secret = PRF(pre_master_secret, "master secret", ClientHello.random + ServerHello.random) [0..47]; = P_hash(pre_master_secret, "master secret" + ClientHello.random +ServerHello.random)[0..47] 固定ラベル 48バイトまで計算 重要:PRFはTLSで他にも様々な要素の計算に用いられます。
  80. 80. 演習: TLS1.2 master_secretを計算する var crypto = require('crypto'); var PRF12 = require('seccamp2015-tls').PRF12; var pre_master_secret = crypto.randomBytes(48); var client_random = crypto.randomBytes(32); var server_random = crypto.randomBytes(32); function MyPRF12(secret, label, seed, size) { return MyP_hash('sha256', secret, Buffer.concat([label, seed]), size); } var label = new Buffer("master secret"); var master_secret = PRF12(pre_master_secret, label, Buffer.concat([client_random, server_random]), 48); var Mymaster_secret = MyPRF12(pre_master_secret, label, Buffer.concat([client_random, server_random]), 48); console.log(master_secret); console.log(Mymaster_secret); console.log(master_secret.equals(Mymaster_secret)); ラベルは master secret labelとseedを結合して新 しい seed を生成 master_secretは48バイト
  81. 81. KeyExpansion • TLSで必要な鍵は、 MAC用、共有鍵用、初期ベクトル(IV)用の3種類。 Client/Serverそれぞれが必要なので6つ必要。 • それぞれで必要なサイズは暗号方式で異なる。 • TLSで必要な鍵は48バイトのMasterSecretでは、サイズが足りない。 • MasterSecretからPRFで必要なサイズのkey_blockに伸長させる。 client_write_MAC server_write_MAC client_write_key server_write_key client_write_IV server_write_IV master_secret(48バイト) key_block = PRF(master_secret, "key expansion", server_random + client_random); 注意!:master_secret の計算時と順番が逆
  82. 82. KeyExpansion(AES-128-GCM) • client_write_MAC, server_write_MAC: 0バイトx2 (AEADはMAC不要) • client_write_key, server_write_key: 16バイトx2 (128bits鍵長) • client_write_IV, server_write_IV: 4バイトx2 (12バイト中の頭、後述) 合計: 40バイト 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 client_write_key(16bytes) server_write_key(16bytes) client_write _IV(4bytes) server_write _IV(4bytes) key_block = PRF12(algo, master_secret, "key expansion", ServerHello.random+ClientHello.random, 40);
  83. 83. 演習:KeyBlockの計算 function KDF(pre_master_secret, client_random, server_random) { var master_secret = PRF12(pre_master_secret, "master secret", Buffer.concat([client_random, server_random]), 48); // 40 bytes key_block for AES-128-GCM var key_block_reader = new DataReader( PRF12(master_secret, "key expansion", Buffer.concat([server_random, client_random]), 40)); return { master_secret: master_secret, client_write_MAC_key: null, server_write_MAC_key: null, client_write_key: key_block_reader.readBytes(16), server_write_key: key_block_reader.readBytes(16), client_write_IV: key_block_reader.readBytes(4), server_write_IV: key_block_reader.readBytes(4) }; } ラベルは key expansion 結合の順番が反対 AES-128-GCM は40バイト分必要 GCMはMACはいらない AES-128の秘密鍵は16バイト 初期ベクトルの最初の4バイト分は両者で秘密 共有、残り8バイトはフレームに付加して送る
  84. 84. ChangeCipherSpec struct { enum { change_cipher_spec(1), (255) } type; } ChangeCipherSpec; 送信元が暗号開始を宣言。これを送信した後は暗号通信を行う。 Record Layer ChangeCipherSpec ContentType Version length (2byte)major minor 0x14 0x03 0x03 0x00 0x01 0x01
  85. 85. Finished struct { opaque verify_data[verify_data_length]; } Finished; verify_data = PRF(master_secret, finished_label, Hash(handshake_messages))[0..11]; finished_label: クライアントは、"client finished"、サーバは"server finished" 12バイト固定 これまでのハンドシェイクデー タ(ただし自分は除く)のハッ シュを計算 TLS1.2では SHA256を使う Finishedを受信すると、これまで送受信したハンドシェイクデータから計算した値と比較。 ハンドシェイクデータが改ざんされてないことを確認する。
  86. 86. Finishedを作る var clientfinished = { master_secret: state.keyblock.master_secret, handshake_message_list: state.handshake_message_list }; var clientfinished = createClientFinished(clientfinished, state); function createClientFinished(json, state) { state.handshake.clientfinished = json; // create session hash var shasum = crypto.createHash('sha256'); shasum.update(Buffer.concat(json.handshake_message_list)); var message_hash = shasum.digest(); var r = PRF12(json.master_secret, "client finished", message_hash, 12); var handshake = createHandshake(handshake_type.finished, r); return createRecord(type.handshake, handshake); } これまで交換したハンド シェイクデータのリスト これまで交換したハン ドシェイクデータの ハッシュ値を求める PRFで12バイト分に 切り詰める フレーム作 成後暗号化 受信したFinished中の値と比 較して改ざんチェック
  87. 87. データの暗号化struct { ContentType type; ProtocolVersion version; uint16 length; select (SecurityParameters.cipher_type) { case stream: GenericStreamCipher; case block: GenericBlockCipher; case aead: GenericAEADCipher; } fragment; } TLSCiphertext; レコードフィールド 暗号化した後の長さ ストリーム暗号、ブ ロック暗号、AEAD で構造が変わる。 Record Layer 暗号化されたデータ ContentType Version length (2byte)major minor 0x03 0x03 …..
  88. 88. データの暗号化(AEAD) struct { opaque nonce_explicit[record_iv_length]; aead-ciphered struct { opaque content[TLSCompressed.length]; }; } GenericAEADCipher; AEADEncrypted = AEAD-Encrypt(write_key, nonce, plaintext, additional_data) struct { opaque salt[4]; opaque nonce_explicit[8]; } GCMNonce; additional_data = seq_num + TLSCompressed.type + TLSCompressed.version + TLSCompressed.length; key blockから生成 した4bytes 毎回生成する乱数 (8bytes 丸見え) uint16 0から始まる 認証データ 暗号化する前の長さ TLSレコード層の情報
  89. 89. AEAD(AES-128-GCM)で暗号化されたデータ Record Header explicit nonce (8 byte) 暗号化されたデータ tag (16 bytes)Cont entTy pe Version length (2byte) major minor 0x03 0x03 AAD writeSeq + Record Header 暗号化する平文 AES-128-GCM 暗号化されたデータ tag write_key 初期ベクトル writeIV(4bytes) + explicit nonce(8bytes) explicit nonce、暗号データ、 tag を合わせた長さに再計算
  90. 90. アプリケーションデータの暗号化 function EncryptAEAD(frame, state) { var key = state.keyblock.client_write_key; var iv = Buffer.concat([state.keyblock.client_write_IV.slice(0,4), state.nonce_explicit]); var record_header = frame.slice(0, 5); var aad = Buffer.concat([state.write_seq, record_header]); var ret = Encrypt(frame.slice(5), key, iv, aad); var encrypted = ret.encrypted; var tag = ret.tag; // re-calcuate length with adding nonce_explit and tag length var length = state.nonce_explicit.length + encrypted.length + tag.length; record_header.writeUIntBE(length, 3, 2); // increment write sequence number incSeq(state.write_seq); return Buffer.concat([record_header, state.nonce_explicit, encrypted, tag]); } record長の再計算 sequence noを増加 初期ベクトルはwrite_IV(4) と explicit nonceを合わせたもの
  91. 91. 秘密鍵漏洩の脅威 • TLS_RSA_WITH_AES_128_GCM_SHA256は、鍵交換・署名にRSA を利用している。 • 通信経路に pre_master_secret を暗号化して相手に送信。 • 公開鍵・秘密鍵共に長期に固定化されている。 • 暗号強度が低い又は秘密鍵が漏えいしてしまうとどうなるか?
  92. 92. 演習: TLSを破る 時間があれば行います。 サーバの秘密鍵をお渡しします。 秘密鍵とハンドシェイクデータから暗号化されたアプリ通信を 解読する。
  93. 93. 演習: TLSを破る • https://github.com/shigeki/SecCamp2015-TLS/tree/master/break_tls • 秘密鍵のパスワードは口頭でお伝えします。 戻し方 $ openssl rsa -in server_encrypted.key -out server.key Enter pass phrase for server_encrypted.key: writing RSA key 秘密鍵と handshake.json のデータから暗号化されたApplication Data を復号してください。
  94. 94. 演習回答: Record Layer Handshake (ClientHello) type protocol version length (2byte) msg type length (3byte) client version random session id cipher suite compr ession Extensi on major minor major minor 0x16 0x03 0x01 ?? ?? 0x01 ?? ?? ?? 0x03 0x03 32 byte 可変 可変 可変 可変 5+4+2=11bytes 先から32byte Record Layer(5bytes) Handshake(ClientKeyExchange) type protocol version length (2bytes) msg type length (3byte) Encrypted PreMasterSecret major minor 0x16 0x03 0x03 ? + 4 0x10 ? 長さ2バイト ? Client/Server Randomの取得 5+4+2=11bytes 先から最後まで 暗号化されたpre master secretの取得 秘密鍵で復号化
  95. 95. 演習回答: Record Header explicit nonce (8 byte) 暗号化されたデータ tag (16 bytes)Cont entTy pe Version length (2byte) major minor 0x03 0x03 sequence noと合わせて AAD ただし長さは再計算が必要 writeIVと合わせてIV 復号化でセットするタグ値 ここを復号化して平 文をゲットする
  96. 96. 演習回答:solve.js var DataReader = require('seccamp2015-data-reader').DataReader; var SecCampTLS = require('seccamp2015-tls'); var fs = require('fs'), crypto = require('crypto'); var handshake = require(__dirname + '/handshake.json'); var clienthello = new Buffer(handshake.ClientHello, 'hex'); var serverhello = new Buffer(handshake.ServerHello, 'hex'); var clientkeyexchange = new Buffer(handshake.ClientKeyExchange, 'hex'); var encryptedApplicationData = new Buffer(handshake.EncryptedApplicationData, 'hex'); // obtain handshake parameters var client_random = clienthello.slice(11, 11+32); var server_random = serverhello.slice(11, 11+32); var encrypted_pre_master_secret = clientkeyexchange.slice(11); // obtain private key var private_key = fs.readFileSync(__dirname + '/server.key'); JSONデータからハンド シェイクデータを抽出 ハンドシェイクパラ メータを抽出 秘密鍵の入手
  97. 97. 演習回答: // decrypt pre master secret var pre_master_secret = crypto.privateDecrypt( {key: private_key, padding: require('constants').RSA_PKCS1_PADDING }, encrypted_pre_master_secret); // objtain keyblock var keyblock = SecCampTLS.KDF(pre_master_secret, client_random, server_random); // Calculate Sequence Number var read_seq = (new Buffer(8)).fill(0); read_seq[7] = 0x01; 秘密鍵を使って ClientKeyExchangeで暗 号化されたpre master secret の復号化 pre master secretとclient/server random を使ってkey block を生成 sequence number を生成
  98. 98. 演習回答: var reader = new DataReader(encryptedApplicationData); // Obtain AEAD parameters var record_header = reader.readBytes(5); var length = record_header.readUIntBE(3, 2); var frame = reader.readBytes(length); var nonce_explicit = frame.slice(0, 8); var encrypted = frame.slice(8, frame.length - 16); var tag = frame.slice(-16); // Re-Caluclate record header record_header.writeUIntBE(encrypted.length, 3, 2); var iv = Buffer.concat([keyblock.client_write_IV, nonce_explicit]); var aad = Buffer.concat([read_seq, record_header]); 暗号化されたアプリケーションデータ からAEADパラメータを抽出する record headerの長さ再計算
  99. 99. 演習回答: // Decrypt Application Data var decipher = crypto.createDecipheriv('aes-128-gcm', keyblock.client_write_key, iv); decipher.setAuthTag(tag); decipher.setAAD(aad); var clear = decipher.update(encrypted); decipher.final(); console.log(clear.toString()); これまで得られたパラメー タからデータの復号化 平文の取得
  100. 100. Perfect Forward Secrecy TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256を使う
  101. 101. Perfect Forward Secrecy(PFS) • 前方秘匿性 • セッション毎に一時的な鍵を使う。 • ハンドシェイクを含む全暗号データを取得されているような状況でも、 将来的な秘密鍵漏洩などのリスクに対応する。 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 Ephemeral:一時的な 鍵交換手法
  102. 102. ECDHEのハンドシェイク ClientHello + elliptic_curves(10) + ec_point_formats(11) ServerHello + ec_point_formats(11) Certificate ServerKeyExchange ServerHelloDone ClientKeyExchange ChangeCipherSpec Finished ChangeCipherSpec Finished Application Data (赤文字が追加変更されるところ) ClientHello拡張を追加。 ServerHello拡張を追加。 楕円曲線名とServerの公 開鍵を署名付きで送付 Clientの公開鍵を送付 ECPointの書式を合意 使える楕円曲線名とECPoint書式を通知
  103. 103. ECDHE ClientHello拡張 struct { NamedCurve elliptic_curve_list<1..2^16-1> } EllipticCurveList; enum { sect163k1 (1), 省略, secp256r1 (23), 省略, (0xFFFF) } NamedCurve; クライアントがサポートしている楕円曲線のリストをサー バ側に通知。サーバはリストの中から適切な楕円曲線を選 び ServerKeyExchange内で選択した楕円曲線を通知する 0 1 2 3 4 5 6 7 elliptic_curves(10) リスト長 データ長 secp256r1 (23) 0x00 0x0a 0x00 0x04 0x00 0x02 0x00 0x17
  104. 104. ECDHE Client/Server Hello拡張 enum { uncompressed (0),省略, reserved (248..255) } ECPointFormat; struct { ECPointFormat ec_point_format_list<1..2^8-1> } ECPointFormatList; 楕円暗号の公開鍵の書式 0 1 2 3 4 5 ec_point_formats(11) リスト長 データ長 uncompressed(0) 0x00 0x0b 0x00 0x02 0x01 0x00
  105. 105. ECDHE ServerKeyExchange select (KeyExchangeAlgorithm) { case ec_diffie_hellman: ServerECDHParams params; Signature signed_params; } ServerKeyExchange; struct { ECParameters curve_params; ECPoint public; } ServerECDHParams; struct { SignatureAndHashAlgorithm algorithm; opaque signature<0..2^16-1>; } DigitallySigned; ServerECDHParams Signature ECParameters ECPoint algorithm signaturecurve_type named_curve 長さ public key (Hello拡張指定の書式) RSA-SHA256 (0x04,0x01)named_curve (3) secp256r1 (23) signature = sign(algorithm, ClientHello.random + ServerHello.random + ServerECDHParams); RSA秘密鍵で ServerECDHParms とRandomを署名
  106. 106. ECDHE ClientKeyExchange struct { select (KeyExchangeAlgorithm) { case ec_diffie_hellman: ClientECDiffieHellmanPublic; } exchange_keys; } ClientKeyExchange; struct { select (PublicValueEncoding) { case implicit: struct { }; case explicit: ECPoint ecdh_Yc; } ecdh_public; } ClientECDiffieHellmanPublic; ECDHEは explicit ClientECDHParams ECPoint 長さ public key (Hello拡張指定の書式) ClientKeyExchangeは署 名の必要はない
  107. 107. 演習: ECDHE公開鍵の守られ方の違い • ServerKeyExchange: 公開鍵を署名 • ClientKeyExchange: やりたい放題 どうしてでしょう?
  108. 108. TLS最新情報 TLS1.3(*)とはどういうものか? (* 注: 2015-7-23時点のものです。最終仕様で変更になる可能性があります。)
  109. 109. TLS1.3(*)の背景 • 2008年 TLS1.2仕様化から7年 • 古い暗号やプロトコルの危殆化に伴う機能の抜本的な見直し • 常時TLS化を目指し、将来的に安心で強固なセキュリティの必 要性 • モバイル環境の普及やWebアプリの高度化に伴う高パフォーマ ンス、低レイテンシー化要望の高まり
  110. 110. TLS1.3の目的 1. ハンドシェイクデータをできるだけ暗号化して隠匿する 2. ハンドシェイクレイテンシーの削減 • 再接続の場合は、 0-RTT • フルハンドシェイクは、 1-RTT 3. ハンドシェイクで交換する項目の見直し 4. レコード層暗号化の見直し(RC4廃止、CBCの不採用)
  111. 111. TLS1.3の構造(*) I P ヘ ッ ダ T C P ヘ ッ ダ TLS Record Layer (5バイト) タイプ (4種類) (1byte) バージョン 0x0301に固定 (2byte) 長さ (2byte) Handshake (タイプ:0x16) msgタイプ (10種類) 長さ ハンドシェイクデータ Alert (タイプ:0x15) レベル 理由 Application Data (タイプ:0x17) 暗号化されたデータ msg タイプ ハンドシェイクデータの種類 0x00 reserved(旧HelloRequest廃止) 0x01 ClientHello 0x02 ServerHello 0x04 NewSessionTicket 0x06 HelloRetryRequest 0x07 ServerKeyShare 0x0b Certificate 0x0c reserved(旧ServerKeyExchange廃止) 0x0d CertificateRequest 0x0e ServerConfigration 0x0f CertificateVerify 0x10 reserved(旧ClientKeyExchange廃止) 0x14 Finished TLS Handshakeは、この12 種類に増加。後方互換のた め3つは予約。 Early Handshake (タイプ:0x19) msgタイプ 長さ ハンドシェイクデータ ChangeCipherSpecを廃止 (* 注: 2015-7-20時点のものです。最終仕様で変更になる可能性があります。) Extens ion ID Extension 0x00d signature_algorithms TBD early_data TBD supported_groups TBD known_configration TBD pre_shared_key TBD client_key_shares
  112. 112. TLS1.3 ハンドシェイク (full handshake) ServerHello ServerKeyShare EncryptedExtensions ServerConfigration Certificate Finished Finished Application Data Application Data (赤文字は暗号化されているデータ) ClientHello + ClientKeyShare 1-RTT Application Data ここで即 暗号化
  113. 113. ServerHello ServerKeyShare EncryptedExtensions ServerConfigration Certificate Finished Finished Application Data Application Data (赤文字は暗号化されているデータ) ClientHello + ClientKeyShare 2-RTT Application Data TLS1.3 ハンドシェイク (鍵交換ができなかった時) ClientHello + ClientKeyShare HelloRetryRequest ここで即 暗号化
  114. 114. TLS1.3 ハンドシェイク (再接続) ServerHello + KnownConfigration + EarlyDataIndication ServerKeyShare Finished Finished Application Data (赤文字は暗号化されているデータ) ClientHello + ClientKeyShare + KnownConfigration + EarlyDataIndication ApplicationData 0-RTT Application Data 以前のサーバ公開 鍵と組み合わせて フライイングでア プリデータ暗号化 して送る
  115. 115. TLS1.3 0-RTTの問題点 0-RTT ApplicationData POST / HTTP/1.1 xxxx 0-RTT ApplicationData POST / HTTP/1.1 xxxx クラスタリング 厳密な同期は不可能 Reply 攻撃 Reply攻撃に弱いため、最初のデータは冪等性のあるリク エストのみに制限しなければならない 更新 更新
  116. 116. TLS1.3 鍵生成(Server view) Ephemeral Secret Static Secret xES xSS Master Secret Early Data Traffic Keys Application Traffic Keys Handshake Traffic Keys Exporter Secret Resumption Secret Finished Secret Server SecretKey in KnownConfigration Client PubKey in ClientKeyShare ClientPubKey in ClientKeyShare Server SecretKey DH or ECDH鍵交換 HKDF DH or ECDH鍵交換 HKDF HKDF seedHKDF key HKDF(label + session_hash) ハンドシェイク暗号化用 アプリデータ暗号化用 Finished用 以前に送付した古い の。最初なら鍵生成 したもの。
  117. 117. TSL1.3変更点まとめ(*) • Compression, Renegotiationの廃止 • ChangeCipherSpec廃止 • ClientKeyExchange廃止してClientHelloの拡張フィールドに • HelloRequest/ServerHello廃止 • Record層のバージョンを 0x03,0x03(TLS1.0)に固定 • ServerConfigrationをクライアントに渡し、0-RTT接続を実現 • ServerKeyShare後即暗号化、証明書データも隠匿 • 乱数から時間の gmt フィールド廃止 (* 注: 2015-7-23時点のものです。最終仕様で変更になる可能性があります。)
  118. 118. TSL1.3変更点まとめ(*) • 鍵交換は名前付きDH,ECDHで ephemeral利用のみ • 鍵生成は、HKDF利用に変更。Ephemeral/Staticの2種類のsecret からsession_hashを付けて各用途別に生成。 • 暗号モードで利用できるのはAEADのみ(GCM, CCM, Poly1305) • AEADの初期ベクタ廃止 • Record層のLengthをAEADで認証外に • 他にも色々・・・ (* 注: 2015-7-23時点のものです。最終仕様で変更になる可能性があります。)

×