では、ストリーム暗号利用時のTLSCiphertext構造体から見ていこう(図14)。type、versionの各フィールドは、そのサイズや意味いずれもTLSPlaintext、TLSCompressedと変わりない。またlengthフィールドは、この構造体のfragmentフィールドの長さを示している。
異なるのはfragmentフィールドだ。TLSCompressed構造体では、fragmentフィールドに圧縮済みデータが含まれていた。TLSCiphertext構造体では、圧縮済みデータ(図ではcontentと表示)に続いて、さらにMACデータが付加されたものになる。
このMACとはMessage Authentication Codeを省略したものだ。日本語にすれば「メッセージ認証コード」とでもなり、単純な認証情報のようにも見えるが、実際には、データ本体の内容を要約した情報と、通信相手と自分だけが知っている秘密の情報が含まれている。そのため、1つの情報で、通信相手の認証と、メッセージの改ざん検出の、両方が行えるようになっている。前編で登場した「メッセージダイジェスト」はこのMACを指したものだ。MACの具体的な生成アルゴリズムについては、後ほど詳しく説明しよう。
TLSCiphertext構造体のfragmentフィールドに格納されるデータサイズは、最大で2の14乗+2048バイトと定義されている。TLSCompressedのfragmentフィールドサイズが最大2の14乗+1024バイトなので、これはそれより1024バイト大きいことになる。
ここで気を付けたいのは、このフィールドに含まれるのが「圧縮済みデータにMACをつなげたものを『暗号化した』データ」である点だ。TLSCiphertext構造体に格納された時点で、すでにfragmentフィールドに含まれているデータは暗号化されている。そのため、図ではfragment内部にフィールドの区切りがあるように表現しているが、論理的にはこの区切りは表面から見えないものと考える必要がある。一方、type、version、lengthの各フィールドは、TLSCiphertext構造体であっても、暗号化されないままで格納されている。TLSCiphertext構造体を見るにあたってはこの点に留意しておこう。
暗号化を行うのであれば、フィールドサイズに問題はないのだろうか。確認しておこう。まず、圧縮済みデータは最大で2の14乗+1024バイトである。また、MACは使用するハッシュアルゴリズム(ダイジェスト生成アルゴリズム)によってサイズが異なり、通常は16バイト(MD5使用時)または20バイト(SHA-1使用時)になる。これらをつなげたデータ(最大2の14乗+1024+最大20)に暗号化操作を施して、そのサイズが2の14乗+2048バイトを超えなければよい。
例えば暗号化アルゴリズムにDESを使用した場合、暗号化前と暗号化後でデータサイズは変わらない。ゆえに暗号化後のデータは十分2の14乗+2048バイトに収まることになる。なお、lengthフィールドに含まれる値は、この暗号化後データのサイズである。
次にブロック暗号利用時のTLSCiphertext構造体を説明しよう(図15)。基本的な構造やフィールドの意味はストリーム暗号利用時とほぼ同じだ。異なるのは、paddingフィールド、padding_lengthフィールドが追加されている点である。
暗号化アルゴリズムにブロック暗号を利用する場合、fragmentフィールドのサイズは、そのアルゴリズムで規定するブロックサイズの整数倍に調整しなければならない。paddingフィールドとpadding_lengthフィールドは、その調整のために利用されるものだ。
paddingフィールドのサイズは0から255までのいずれかの長さを取る。padding_lengthのフィールドのサイズは1バイトで、paddingフィールドのサイズとして0から255までの整数を格納する。paddingフィールド、そして、このpadding_lengthフィールド分の1バイトも含めて、fragmentフィールド全体がブロックサイズの整数倍になるよう調整を行うことになる。
padding_lengthの値を決めるには、まずcontentのバイトサイズとMACのバイトサイズに1(padding_lengthのバイトサイズ)を加え、それを暗号化アルゴリズムのブロックサイズで割る。その余りをブロックサイズから引くことで、padding_lengthの値(=パディングフィールドのサイズ)が得られる。具体的に計算をしてみると、contentが61バイト、MACが20バイト、ブロックサイズが8のとき、paddingフィールドのサイズは8−(61+20+1) mod 8 = 6バイトになる(図16)。
この6バイトのpaddingフィールドはどんな値で埋めるのだろうか。それにはpadding_legnthフィールドの値を使用するよう定義されている。つまり、前出の例では、paddingとpadding_lengthに相当する部分の値は、0x06 0x06 0x06 0x06 0x06 0x06 0x06 となるわけだ。これはパディング処理を容易にするための配慮と考えられる。
ところで、この例ではpadding_lengthを6としたが、ブロックサイズの整数倍化という意味では、14、22、30など、6に8の倍数を加えた値でも条件は成り立つ。こういう指定は可能なのだろうか。
これに関して、SSLの仕様書では、padding_lengthはブロックサイズより小さくなると書かれている。そのためSSLではこういった指定は許容されない。一方、TLSの仕様書によると、パディングはブロックサイズの整数倍になることは求められているが、ブロックサイズより小さくする必要はない。そのため、こういった値を使ったパディングをしてよいことになる。
このような許容が行われたのには、仕様を寛容にしたという面もあるのだろうが、それよりも攻撃への耐性を向上させるという意味が強い。TLSCiphertext構造体のlengthフィールドは暗号化されておらず、この解析によって攻撃への足がかりを与えてしまう可能性がある。ブロック数の整数倍パディングを許容すれば、メッセージ長の解析を多少なりともやりづらくする効果があると考えられる。
Copyright © ITmedia, Inc. All Rights Reserved.