ssl/tlsの基礎と最新動向

118
SSL/TLSの基礎と最新動向 セキュリティキャンプ 2015 2015812IIJ 大津 繁樹 更新版資料の置場 http://goo.gl/cX1M17 Github Repo: https://goo.gl/vRLzrj

Upload: shigekiohtsu

Post on 18-Aug-2015

17.116 views

Category:

Technology


9 download

TRANSCRIPT

Page 1: SSL/TLSの基礎と最新動向

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

2015年8月12日

IIJ 大津繁樹

更新版資料の置場 http://goo.gl/cX1M17

Github Repo: https://goo.gl/vRLzrj

Page 2: SSL/TLSの基礎と最新動向

自己紹介

•大津繁樹

•株式会社インターネットイニシアティブ• プロダクト本部アプリケーション開発部サービス開発2課

• NodeJS Technical Committee メンバー• (主にTLS/CRYPTO/OpenSSLバインディングを担当)

• IETF httpbis WG で HTTP/2相互接続試験等仕様策定に参画。

•ブログ: http://d.hatena.ne.jp/jovi0608/

Page 3: SSL/TLSの基礎と最新動向

はじめに• TLS(Transport Layer Security)の仕組みについて学んでいただきます。

•後述するようTLSは、様々なセキュリティの要素技術から成り立っており、その一つ一つが難解で深い技術要素です。

•残念ながら4時間もの時間があってもその全てを完全に理解することは容易ではありません。

Page 4: SSL/TLSの基礎と最新動向

本講義の目的

• TLSの本質は、要素技術をどう組み合わせてどういう手順でセキュアな通信を確立するかというところにあります。そのため、本講義の目的は、TLS技術の基礎

「TLSハンドシェイクの仕組み」

を理解していただくことです

•聞いているだけの理解より、実際に手を動かしての体験する方を重視して進めます。

•課題内容は空白にしています。講義当日にお知らせします。

Page 5: SSL/TLSの基礎と最新動向

本講義の内容

• TLSの概要

• TLSを理解する準備

• TLSの話• まずは TLS_RSA_WITH_AES_128_GCM_SHA256 の時から

• Perfect Forward Secrecy• TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256を使う

•最新情報 TLS1.3とはどういうものか?概要説明

Page 6: SSL/TLSの基礎と最新動向

まずやってみる

モジュールのインストール

$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

キーボードを打ってみよう

(注:エラー処理やサニタイジングが十分でないのであくまでテスト用で利用すること)

Page 7: SSL/TLSの基礎と最新動向

TLSの概要

Page 8: SSL/TLSの基礎と最新動向

インターネットの脅威 盗聴

パスワードやクレジットカード番号を盗み見

Page 9: SSL/TLSの基礎と最新動向

インターネットの脅威 改ざん

通信途中でデータを書き換え

Page 10: SSL/TLSの基礎と最新動向

インターネットの脅威 なりすまし

ユーザになりすまして通信を行う

Page 11: SSL/TLSの基礎と最新動向

インターネットの脅威 否認

そんな通信してませんと否認する

Page 12: SSL/TLSの基礎と最新動向

インターネットの脅威から守るセキュリティ対策

盗聴

改ざん 成りすまし

否認

暗号化

完全性チェック

認証

署名

Page 13: SSL/TLSの基礎と最新動向

各レイヤーにおけるセキュリティ通信

WPA

IPsec

TLS,DTLS,SSH

S/MIME, PGP

無線LAN

IP

TCP, UDP

データ

Page 14: SSL/TLSの基礎と最新動向

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.

アプリ アプリ

完全性

プライバシー

Page 15: SSL/TLSの基礎と最新動向

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

現在の利用推奨

様々な拡張仕様の追加

Page 16: SSL/TLSの基礎と最新動向

TLSを理解する準備

Page 17: SSL/TLSの基礎と最新動向

TLSの要素技術

X509証明書

PKI

対称暗号

暗号モード

公開鍵暗号

デジタル署名

メッセージ認証

乱数生成

TLS鍵交換

一方向ハッシュ

TLSプロトコルは、これらの要素技術を組み合わせてアプリ間のセキュア通信を確立する手順を決める

Page 18: SSL/TLSの基礎と最新動向

TLS要素技術の依存性

X509証明書

PKI

対称暗号

暗号モード

公開鍵暗号

デジタル署名 メッセージ認証

乱数生成

鍵交換 一方向ハッシュ

本来はこの一つ一つをきちんと理解してもらうのが必要

Page 19: SSL/TLSの基礎と最新動向

TLS要素技術の依存性

X509証明書

PKI

対称暗号

暗号モード

公開鍵暗号

デジタル署名 メッセージ認証

乱数生成

鍵交換 一方向ハッシュ

GCM

AES

ECDHE RSA

SHA256

HMAC

本日の講義で扱う技術

説明は概要だけですが、演習で実際の動作を手を動かして体験してもらいます。

Page 20: SSL/TLSの基礎と最新動向

要素技術と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を割り当て

Page 21: SSL/TLSの基礎と最新動向

乱数生成

利用用途:

•暗号鍵(対称暗号:秘密鍵、公開鍵暗号:鍵ペア)の生成

•暗号モードの初期ベクトルやNonce(*)の生成

• MAC(メッセージ認証)用鍵

(* Nonce(number used once)一度だけ使い捨て用に使われる数字

求められる機能無作為性:偏りがなく等しい数である。予測不可能性:次の乱数が予想できない。制限負可能性:同じ乱数列を再現できない。

Page 22: SSL/TLSの基礎と最新動向

乱数生成

•実際の利用は、疑似乱数生成。seedが必要。

• OpenSSLでは、seedはLinuxの/dev/urandomを利用。WindowsではOSのAPIのCryptGenRandomだけでなく画面スクリーンのビットマップハッシュも利用。

脆弱性:

• CVE-2008-0166: DebianやUbuntuのOpenSSLに予測可能な乱数を生成してしまう脆弱性

• SSH公開鍵にブルートフォース攻撃

Page 23: SSL/TLSの基礎と最新動向

対称暗号

暗号文平文

共通鍵 共通鍵

平文

ストリーム暗号:データを逐次暗号化(RC4, Chacha20)

ブロック暗号:データをブロック毎に暗号化(DES, AES)

幾つかの暗号では既に危殆化:DES:2005年 NIST FPS46-3規格の廃止(2030年までは許容)

RC4: RFC7455: Prohibiting RC4 Cipher Suites

暗号化 復号化

Page 24: SSL/TLSの基礎と最新動向

対称暗号 AES

• 1997年よりプロジェクト開始、2000年選定、2001年仕様発行

•ブロックサイズ 128bit

•鍵長: 128bits, 192bits, 256bits の3種類

• Intel/AMDのCPUでハードウェア処理のサポート AES-NI

Page 25: SSL/TLSの基礎と最新動向

暗号モード

•ブロック暗号は同じデータを同じ鍵で暗号化すると毎回同一の暗号文になる。

•ブロック長より長いデータを暗号化する場合に暗号モードを利用して繰り返しを避ける。

• CBC:「(平文 XOR ベクトル) を暗号化」を続ける

• CTR:「カウンターを暗号化 XOR 平文」を続ける

実際にTLSで利用するには改ざん検知のためのMAC(メッセージ認証)との組み合わせる(AEAD)。

これまでの主流

これからの主流に(GCM後述)

Page 26: SSL/TLSの基礎と最新動向

AEAD(認証付き暗号)

暗号化しないけど改ざん防止が必要なデータ(ヘッダ等)

暗号化する平文

AEAD暗号化

暗号文 認証タグ

共通鍵

初期ベクトル

Page 27: SSL/TLSの基礎と最新動向

AEAD(認証付き暗号)

平文

AEAD復号化

改ざんチェック

暗号化しないけど改ざん防止が必要なデータ(ヘッダ等)

暗号文 認証タグ

共通鍵

初期ベクトル

Page 28: SSL/TLSの基礎と最新動向

GCM

• GCM (Galois Counter Mode: ガロアカウンターモード)

• CTRとGHASHを組み合わせたAEAD

•ハードウェア処理で高速化が可能

• AESと組み合わせて AES-GCMとして利用

Page 29: SSL/TLSの基礎と最新動向

一方向ハッシュ

データ 一方向ハッシュ関数

ハッシュ値

ハッシュ値を比較することでデータの改ざんをチェックすることができる。

Page 30: SSL/TLSの基礎と最新動向

一方向ハッシュ

• 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より正式公開

Page 31: SSL/TLSの基礎と最新動向

メッセージ認証(HMAC)

•事前に共通鍵を共有

•共通鍵とデータを組み合わせたハッシュ値を作成

•データの完全性とハッシュ作成者を認証する

データ 一方向ハッシュ関数

ハッシュ値

共通鍵

Page 32: SSL/TLSの基礎と最新動向

公開鍵暗号

512bit RSAの危険性 FREAK https://freakattack.com/

•解を求めるのが困難な数学的問題を利用して暗号を生成。

•公開鍵と秘密鍵のペアを生成。公開鍵はさらして大丈夫。

•公開鍵で暗号化し秘密鍵で復号化。

• RSA

• ECC(楕円曲線暗号)

公開鍵 秘密鍵

暗号化 復号化

Page 33: SSL/TLSの基礎と最新動向

鍵交換

• 2者間で安全に鍵を共有する仕組み

•互いに公開鍵を交換しあい、共有鍵を生成する。

•通信経路上で共有鍵のやり取りがない

• DH (Diffie-Hellman)

• ECDH(楕円曲線DH)

512bit DH Logjam https://weakdh.org/

Page 34: SSL/TLSの基礎と最新動向

デジタル署名

•データの完全性のチェックが可能となる。

•データの送信元の認証が可能となる。

•公開鍵の信頼性の範囲で否認防止が可能となる。

• RSA

• DSA,ECDSA

公開鍵秘密鍵 データ+デジタル署名

データハッシュ値を暗号化しデジタル署名を生成

デジタル署名を復号化。データハッシュ値と比較し検証する

Page 35: SSL/TLSの基礎と最新動向

X509証明書(Certificate)

•公開鍵と所有者・発行者やその他属性情報をデジタル署名したデータ

•元々は電子ディレクトリサービス仕様(X500)の一部

•認証局(CA)が所有者の実体を確認して証明書を発行する(PKI)

Page 36: SSL/TLSの基礎と最新動向

X509証明書(Certificate)

Page 37: SSL/TLSの基礎と最新動向

演習:

sudo npm install -g seccamp2015-crypto-workshopper

•乱数生成

• AES-GCM

•公開鍵暗号

•一方向ハッシュ

•鍵交換

•メッセージ認証

•デジタル署名

• X509証明書 (時間がなさそうなので取りやめました)

Page 38: SSL/TLSの基礎と最新動向

TLSの話

まずは TLS_RSA_WITH_AES_128_GCM_SHA256 の時から

注:複雑さを避けるためクライアント認証機能は説明しません

Page 39: SSL/TLSの基礎と最新動向

TLSデータ表現の仕方 (構造体,メンバー)

struct {

uint8 major;

uint8 minor;

} ProtocolVersion;

0 1

majaor minor

ProtocolVersion version = { 3, 3 }; /* TLS v1.2*/

0 1

0x03 0x03

8bit符号なし整数(2バイト)

構造体と同じ

構造体名

Page 40: SSL/TLSの基礎と最新動向

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

Page 41: SSL/TLSの基礎と最新動向

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

0x00SessionIDのサイズが0の場合

SessionIDのサイズが1の場合

SessionIDのサイズが32の場合

Page 42: SSL/TLSの基礎と最新動向

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に割り当てられています。

Page 43: SSL/TLSの基礎と最新動向

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までの可変ベクターのデータが入る

Page 44: SSL/TLSの基礎と最新動向

TLSデータ表現の仕方(読んでみよう)

struct {

ExtensionType extension_type;

opaque extension_data<0..2^16-1>;

} Extension;

enum {

signature_algorithms(13), (65535)

} ExtensionType;

Page 45: SSL/TLSの基礎と最新動向

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>;

Page 46: SSL/TLSの基礎と最新動向

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;

Page 47: SSL/TLSの基礎と最新動向

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種類に分かれる。

Page 48: SSL/TLSの基礎と最新動向

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タイプの種類でそれぞれの構造を参照する

Page 49: SSL/TLSの基礎と最新動向

TLSハンドシェイク

まずは TLS_RSA_WITH_AES_128_GCM_SHA256 の時から

Page 50: SSL/TLSの基礎と最新動向

TLSハンドシェイク(full handshake)ClientHello

ServerHello

Certificate

ServerHelloDone

ClientKeyExchange

ChangeCipherSpec

Finished

ChangeCipherSpec

Finished

Application Data

Application Data

(赤文字はハンドシェイク)

ClientHelloとServerHelloのやり取りで双方が利用するTLSバージョンや暗号化方式などを合意する。

Page 51: SSL/TLSの基礎と最新動向

TLSハンドシェイク(resumption)

ClientHello

ServerHello

ChangeCipherSpec

Finished

ChangeCipherSpec

Finished

Application Data

Application Data

(赤文字はハンドシェイク)

SessionIDによるTLSセッションの再開。鍵交換や証明書送付をスキップ。

今回は演習の対象外です

Page 52: SSL/TLSの基礎と最新動向

TLSハンドシェイクの意味

ClientHello/ServerHello/ServerHelloDoneTLSのための情報交換

バージョン・乱数・暗号方式・拡張情報

Certificate公開鍵情報の送付エンドポイントの認証

ClientKeyExchange/ServerKeyExchange共有鍵交換

ChangeCipherSpec暗号開始の合図

Finishedハンドシェイクデータの改ざんチェック

Page 53: SSL/TLSの基礎と最新動向

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;

Page 54: SSL/TLSの基礎と最新動向

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データ例

Page 55: SSL/TLSの基礎と最新動向

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 可変 可変 可変 可変

Version0x03,0x00 = SSLv3

0x03,0x01= TLSv1.0

0x03,0x02=TLSv1.1

0x03,0x03=TLSv1.2

クライアントが利用できる最高のTLSバージョンを指定、サーバがどのバージョンを使うか選択する

Page 56: SSL/TLSの基礎と最新動向

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'本当はちゃんとした乱数を入れる

Page 57: SSL/TLSの基礎と最新動向

演習:最少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);

});

Page 58: SSL/TLSの基礎と最新動向

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;

複数ではない

複数ではない

Page 59: SSL/TLSの基礎と最新動向

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

Page 60: SSL/TLSの基礎と最新動向

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(): 残っているバイトサイズを返す

Page 61: SSL/TLSの基礎と最新動向

演習: 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)

Page 62: SSL/TLSの基礎と最新動向

演習 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

Page 63: SSL/TLSの基礎と最新動向

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つ目以降は中間証明書など

Page 64: SSL/TLSの基礎と最新動向

ここから先の演習は状態管理が必要

はじめに使った 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

キーボードを打ってみよう

(注:エラー処理やサニタイジングが十分でないのであくまでテスト用で利用すること)

Page 65: SSL/TLSの基礎と最新動向

演習 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バイト分

Page 66: SSL/TLSの基礎と最新動向

ServerKeyExchange

RSA鍵交換では不要。今の時点じゃスキップします。

ECDHEのところで再度説明します。

Page 67: SSL/TLSの基礎と最新動向

ServerHelloDone

struct { } ServerHelloDone;

handshake type handshake長

0x0e 0x00 0x00 0x00

ServerHelloの終了の合図ハンドシェイクヘッダのみ

Page 68: SSL/TLSの基礎と最新動向

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による鍵交換ではクライアントの公開鍵を送る。

Page 69: SSL/TLSの基礎と最新動向

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>の可変ベクター

Page 70: SSL/TLSの基礎と最新動向

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

Page 71: SSL/TLSの基礎と最新動向

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

Page 72: SSL/TLSの基礎と最新動向

PreMasterSecret/MasterSecret

• TLSで利用するIV(初期ベクトル)、共有鍵、MAC鍵のデータ元

• MasterSecretは48バイト長。PreMasterSecretの長さは鍵交換方式に依存する。

• MasterSecretは、PreMasterSecret、ClientRandom、ServerRandom、固定ラベルから生成する。

• Clinet/ServerRandomは全て丸見え。PreMasterSecretは、必ず死守して守らないといけない。これが漏えいするとTLSの安全性は全ておじゃん。

Page 73: SSL/TLSの基礎と最新動向

演習:PreMasterSecretの計算TLS1.2のRSA鍵交換時

function createPreMasterSecretRSAKeyExchange(state) {

var pre_master_secret = (ここを作る)

return pre_master_secret;

}

Page 74: SSL/TLSの基礎と最新動向

演習答え: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バイトは乱数で発生させる

Page 75: SSL/TLSの基礎と最新動向

演習: 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を暗号化

Page 76: SSL/TLSの基礎と最新動向

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の組み合わせ)。

Page 77: SSL/TLSの基礎と最新動向

演習: 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));

Page 78: SSL/TLSの基礎と最新動向

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)を計算

Page 79: SSL/TLSの基礎と最新動向

MasterSecretの計算その2PRF(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で他にも様々な要素の計算に用いられます。

Page 80: SSL/TLSの基礎と最新動向

演習: 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バイト

Page 81: SSL/TLSの基礎と最新動向

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

の計算時と順番が逆

Page 82: SSL/TLSの基礎と最新動向

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);

Page 83: SSL/TLSの基礎と最新動向

演習: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バイトはフレームに付加して送る

Page 84: SSL/TLSの基礎と最新動向

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

Page 85: SSL/TLSの基礎と最新動向

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を受信すると、これまで送受信したハンドシェイクデータから計算した値と比較。ハンドシェイクデータが改ざんされてないことを確認する。

Page 86: SSL/TLSの基礎と最新動向

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中の値と比較して改ざんチェック

Page 87: SSL/TLSの基礎と最新動向

データの暗号化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 …..

Page 88: SSL/TLSの基礎と最新動向

データの暗号化(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 丸見え)

uint160から始まる

認証データ

暗号化する前の長さ

TLSレコード層の情報

Page 89: SSL/TLSの基礎と最新動向

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 を合わせた長さに再計算

Page 90: SSL/TLSの基礎と最新動向

アプリケーションデータの暗号化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を合わせたもの

Page 91: SSL/TLSの基礎と最新動向

秘密鍵漏洩の脅威

• TLS_RSA_WITH_AES_128_GCM_SHA256は、鍵交換・署名にRSAを利用している。

•通信経路に pre_master_secretを暗号化して相手に送信。

•公開鍵・秘密鍵共に長期に固定化されている。

•暗号強度が低い又は秘密鍵が漏えいしてしまうとどうなるか?

Page 92: SSL/TLSの基礎と最新動向

演習: TLSを破る

時間があれば行います。

サーバの秘密鍵をお渡しします。

秘密鍵とハンドシェイクデータから暗号化されたアプリ通信を解読する。

Page 93: SSL/TLSの基礎と最新動向

演習: 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を復号してください。

Page 94: SSL/TLSの基礎と最新動向

演習回答:

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の取得

秘密鍵で復号化

Page 95: SSL/TLSの基礎と最新動向

演習回答:

Record Header explicit nonce

(8 byte)

暗号化されたデータ tag

(16 bytes)Cont

entTy

pe

Version length

(2byte)major minor

0x03 0x03

sequence noと合わせて AAD

ただし長さは再計算が必要writeIVと合わせてIV

復号化でセットするタグ値

ここを復号化して平文をゲットする

Page 96: SSL/TLSの基礎と最新動向

演習回答: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データからハンドシェイクデータを抽出

ハンドシェイクパラメータを抽出

秘密鍵の入手

Page 97: SSL/TLSの基礎と最新動向

演習回答:

// 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 を生成

Page 98: SSL/TLSの基礎と最新動向

演習回答:

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の長さ再計算

Page 99: SSL/TLSの基礎と最新動向

演習回答:

// 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());

これまで得られたパラメータからデータの復号化

平文の取得

Page 100: SSL/TLSの基礎と最新動向

Perfect Forward Secrecy

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256を使う

Page 101: SSL/TLSの基礎と最新動向

Perfect Forward Secrecy(PFS)

•前方秘匿性

• セッション毎に一時的な鍵を使う。

• ハンドシェイクを含む全暗号データを取得されているような状況でも、将来的な秘密鍵漏洩などのリスクに対応する。

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

Ephemeral:一時的な鍵交換手法

Page 102: SSL/TLSの基礎と最新動向

ECDHEのハンドシェイク

ClientHello

+ elliptic_curves(10)

+ ec_point_formats(11)ServerHello

+ ec_point_formats(11)

Certificate

ServerKeyExchange

ServerHelloDone

ClientKeyExchange

ChangeCipherSpec

FinishedChangeCipherSpec

FinishedApplication Data

(赤文字が追加変更されるところ)

ClientHello拡張を追加。

ServerHello拡張を追加。

楕円曲線名とServerの公開鍵を署名付きで送付

Clientの公開鍵を送付

ECPointの書式を合意

使える楕円曲線名とECPoint書式を通知

Page 103: SSL/TLSの基礎と最新動向

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

Page 104: SSL/TLSの基礎と最新動向

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

Page 105: SSL/TLSの基礎と最新動向

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を署名

Page 106: SSL/TLSの基礎と最新動向

ECDHE ClientKeyExchangestruct {

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は署名の必要はない

Page 107: SSL/TLSの基礎と最新動向

演習: ECDHE公開鍵の守られ方の違い

• ServerKeyExchange: 公開鍵を署名

• ClientKeyExchange: やりたい放題

どうしてでしょう?

Page 108: SSL/TLSの基礎と最新動向

TLS最新情報TLS1.3(*)とはどういうものか?

(* 注: 2015-7-23時点のものです。最終仕様で変更になる可能性があります。)

Page 109: SSL/TLSの基礎と最新動向

TLS1.3(*)の背景

• 2008年 TLS1.2仕様化から7年

•古い暗号やプロトコルの危殆化に伴う機能の抜本的な見直し

•常時TLS化を目指し、将来的に安心で強固なセキュリティの必要性

•モバイル環境の普及やWebアプリの高度化に伴う高パフォーマンス、低レイテンシー化要望の高まり

Page 110: SSL/TLSの基礎と最新動向

TLS1.3の目的

1. ハンドシェイクデータをできるだけ暗号化して隠匿する

2. ハンドシェイクレイテンシーの削減• 再接続の場合は、 0-RTT

• フルハンドシェイクは、 1-RTT

3. ハンドシェイクで交換する項目の見直し

4. レコード層暗号化の見直し(RC4廃止、CBCの不採用)

Page 111: SSL/TLSの基礎と最新動向

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

Page 112: SSL/TLSの基礎と最新動向

TLS1.3 ハンドシェイク (full handshake)

ServerHello

ServerKeyShare

EncryptedExtensions

ServerConfigration

Certificate

Finished

Finished

Application Data

Application Data

(赤文字は暗号化されているデータ)

ClientHello

+ ClientKeyShare

1-RTT

Application Data

ここで即暗号化

Page 113: SSL/TLSの基礎と最新動向

ServerHello

ServerKeyShare

EncryptedExtensions

ServerConfigration

Certificate

Finished

Finished

Application Data

Application Data

(赤文字は暗号化されているデータ)

ClientHello

+ ClientKeyShare

2-RTT

Application Data

TLS1.3 ハンドシェイク (鍵交換ができなかった時)

ClientHello

+ ClientKeyShare

HelloRetryRequest

ここで即暗号化

Page 114: SSL/TLSの基礎と最新動向

TLS1.3 ハンドシェイク (再接続)

ServerHello

+ KnownConfigration

+ EarlyDataIndication

ServerKeyShare

Finished

Finished

Application Data

(赤文字は暗号化されているデータ)

ClientHello

+ ClientKeyShare

+ KnownConfigration

+ EarlyDataIndication

ApplicationData

0-RTT

Application Data

以前のサーバ公開鍵と組み合わせてフライイングでアプリデータ暗号化して送る

Page 115: SSL/TLSの基礎と最新動向

TLS1.3 0-RTTの問題点

0-RTT

ApplicationData

POST / HTTP/1.1

xxxx

0-RTT

ApplicationData

POST / HTTP/1.1

xxxx

クラスタリング厳密な同期は不可能

Reply攻撃

Reply攻撃に弱いため、最初のデータは冪等性のあるリクエストのみに制限しなければならない

更新

更新

Page 116: SSL/TLSの基礎と最新動向

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 ClientKeyShareServer SecretKey

DH or ECDH鍵交換

HKDF

DH or ECDH鍵交換

HKDF

HKDF seedHKDF key

HKDF(label + session_hash)

ハンドシェイク暗号化用 アプリデータ暗号化用 Finished用

以前に送付した古いの。最初なら鍵生成したもの。

Page 117: SSL/TLSの基礎と最新動向

TSL1.3変更点まとめ(*)• Compression, Renegotiationの廃止

• ChangeCipherSpec廃止

• ClientKeyExchange廃止してClientHelloの拡張フィールドに

• HelloRequest/ServerHello廃止

• Record層のバージョンを 0x03,0x03(TLS1.0)に固定

• ServerConfigrationをクライアントに渡し、0-RTT接続を実現

• ServerKeyShare後即暗号化、証明書データも隠匿

•乱数から時間の gmtフィールド廃止

(* 注: 2015-7-23時点のものです。最終仕様で変更になる可能性があります。)

Page 118: SSL/TLSの基礎と最新動向

TSL1.3変更点まとめ(*)

•鍵交換は名前付きDH,ECDHで ephemeral利用のみ

•鍵生成は、HKDF利用に変更。Ephemeral/Staticの2種類のsecretからsession_hashを付けて各用途別に生成。

•暗号モードで利用できるのはAEADのみ(GCM, CCM, Poly1305)• AEADの初期ベクタ廃止

• Record層のLengthをAEADで認証外に

•他にも色々・・・

(* 注: 2015-7-23時点のものです。最終仕様で変更になる可能性があります。)