3<- 目次 ->5


4. 表記言語 English

(準備中)

本書においては、データフォーマットをコンピュータの内部表現に依存しない一般的な表現で扱う。構文にはその元になっている構造がいくつか存在する。構文は、C 言語の構文と、XDR [XDR] の構文とその目的に類似しているが、厳密に記述しているわけではない。

 

4.1. 基本ブロックサイズ English

すべてのデータ項目は、明確に定義される。基本的なデータブロックサイズは 1 バイト(すなわち 8 ビット)である。複数バイトで構成されるデータ項目は、バイトを連鎖させたもので、左から右、上から下へバイトデータを連鎖させる。バイトストリームから複数バイトの項目(例えば 1つの数値)を形成するには、(C 記法を使用して)次のように記述する。

value = (byte[0] << 8*(n-1)) | (byte[1] << 8*(n-2)) |

... | byte[n-1];

この複数バイト値におけるバイト順序は、通常のネットワークバイト順序、すなわちビックエンディアン形式である。

 

4.2. その他 English

コメントは"/*"で始まり、"*/"で終わる。

省略できる要素は、"[[ ]]"の、2重括弧で囲む。

解析の行われないデータを含む 1バイトのエンティティを、opaque 型とする。

 

4.3. ベクトル English

ベクトル(1次元配列)は、同種のデータ要素のストリームである。ベクトルのサイズは、コードを記述した時点で指定されるものもあれば、実行時まで不特定な状態であるものもある。どちらの場合でも、長さはベクトルにおけるバイト数であり、要素数ではない。固定長ベクトルのT型である新しい T' 型を指定するための構文は、次のようになる。

T T'[n];

ここで T' は、データストリーム上で nバイトを占有する。n は T のサイズの整数倍である。エンコードされたストリームには、ベクトル長データは含まれない。

次の例では、Datum はプロトコルが解釈しない連続する 3 バイトとして定義される。Data は Datum を 3 つ連続したものであれから、サイズは 9 バイトとなる。

opaque Datum[3]; /* 解析が行われない 3バイト */
Datum Data[9]; /* 3つの連続した 3バイトのベクトル */

可変長ベクトルは、表記 <floor...ceiling> を使用して、規定上の範囲を指定することにより定義される。これがエンコードされると、バイトストリームで、その長さを示すデータがベクトルの内容の前に付加される。このとき、ベクトルで指定した最大長を保持するのに必要なバイト数がベクトルの長さとなる。実際の長さを示すフィールドの値がゼロの可変長ベクトルを、空ベクトルと呼ぶ。

T T'<floor..ceiling>;

以下の例では、mandatory は、300 - 400 バイトの opaque 型のベクトルである。空にはならない。ベクトルの実際の長さを格納するフィールドは 2バイトすなわち uint16 を使用する。これは値 400を格納するのに十分である(4.4 節を参照)。一方、longer は、最大 800 バイト(つまり、unit16 型の要素が 400 個)までを表すことができる。これは、空ベクトルになる可能性がある。これは空ベクトルになってもよい。そのエンコードにおいては、ベクトルの前に、実際の長さを表す 2バイトのフィールドが含まれる。エンコードされたベクトルの長さは、単一要素の長さの整数倍でなければならない(例えば、 uint16 型の 17 バイトのベクトル、というのは無効である)。

opaque mandatory<300..400>;
/* 長さを示すフィールドは 2バイトである。空であってはならない */
uint16 longer<0..800>;
/* ゼロから 400 までの、16 ビット符号なし整数 */

 

4.4. 数値 English

基本的な数値データ型は、符号なしバイト (uint8) である。それより大きい数値データ型はすべて、4.1 章 において示されるような、一連のバイトを連鎖させて固定長とすることにより形成される。それらにもまた符号はない。以下の数値型がすでに定義されている。

uint8 uint16[2];
uint8 uint24[3];
uint8 uint32[4];
uint8 uint64[8];

この仕様書を通じて使用されているすべての値は、「ネットワーク」順序、すなわち「ビックエンディアン」順序として記憶される。16進法で 01 02 03 04 として表される uint32 は、10 進法における値 16909060 に等しい。

 

4.5. 列挙 English

列挙と呼ばれる、不連続な値をもつデータ型が使用される。列挙型のフィールドには、その定義内において宣言された値のみが割り当てられる。それぞれの定義同士は、異なる型をもつ。同じ型をもつ列挙同士のみが代入、比較される。列挙におけるすべての要素には、以下の例で示されるように値が割り当てられなければならない。列挙におけるそれぞれの要素の順番は問われないため、どのような値をどのような順序で割り当てても構わない。

enum { e1(v1), e2(v2), ... , en(vn) [[, (n)]] } Te;

列挙においては、定義されている序数の最大値を表すのに必要なメモリ量をビットストリーム内で占有する。以下の定義では、Color型フィールドとして 1バイトが使用される。

enum { red(3), blue(5), white(7) } Color;

ある値を関連タグなしで指定することにより、型サイズの定義を強制することができる。以下の例では、Taste はデータストリームとして 2 バイトを使用するが、割り当てられている値は 1、2 または 4 だけである。

enum { sweet(1), sour(2), bitter(4), (32000) } Taste;

列挙における各要素の名前は、定義された型の中のみで有効である。最初の例では、列挙の 2 番目の要素に対する正確な参照方法は、Color.blue である。ただし代入される値のターゲットが明白であれば、必ずしもこのように指定する必要はない。

Color color = Color.blue; /* 十分な指定。文法的に正確 */

Color color = blue; /* これは正しい。型が明白。 */

内部でのみ使用され、外部の表記に変換されることのない列挙に関しては、数値情報を省略してもよい。

enum { low, medium, high } Amount;

 

4.6. 構造体 English

構造体は、基本的なデータ型から構成される。それぞれの定義では、新規で一意の型を宣言する。定義構文は、C 言語に似たものである。

struct {

T1 f1;
T2 f2;
...
Tn fn;

} [[T]];

構造体内のフィールドは、列挙において利用可能な構文に似た構文を使用し、型名を使用することで指定できる。例えば、T.f2 は、先の宣言における 2 番目のフィールドを参照する。構造体の定義はネストしてもよい。

4.6.1. 可変構造をもつ構造体 English

構造体では、その環境で利用できる情報に基づいたバリエーションを持つことが出来る。このときのセレクタは、その構造体で定義しているバリエーションを定義するための列挙型でなければならない。select で宣言されている列挙型に含まれるすべての要素に対して、case 文による処理が表記されていなければならない。構造体のバリエーション部分には、参照のためにラベルを付与してもよい。どのバリエーションが実行時に選択されるかのメカニズムについては、ここで使用している言語では規定されない。

struct {

T1 f1;
T2 f2;
....
Tn fn;
select (E) {

case e1: Te1;
case e2: Te2;
....
case en: Ten;

} [[fv]];

} [[Tv]];

例:

enum { apple, orange } VariantTag;
struct {

uint16 number;
opaque string<0..10>; /* 可変長 */

} V1;
struct {

uint32 number;
opaque string[10]; /* 固定長 */

} V2;
struct {

select (VariantTag) { /* セレクタの値が含まれる */

case apple: V1; /* バリエーションの型, tag = apple */
case orange: V2; /* バリエーションの型, tag = orange */

} variant_body; /* バリエーションのラベル(オプショナル)*/

} VariantRecord;

構造体のバリエーションは、型の前にセレクタのための値を指定することによって、定義(固定)することが出来る。例えば、

orange VariantRecord

は、V2 型のバリエーションを持つ、VariantRecord の宣言となる。

 

4.7. 暗号技術的属性 English

4 つの暗号処理、つまりデジタル署名、ストリーム暗号、ブロック暗号、公開鍵暗号では、それぞれ、デジタルでの署名、ストリームの暗号化、ブロックの暗号化、公開鍵による暗号化が行われる。フィールドに対する暗号処理は、そのフィールドの型宣言の前に、適切なキーワードを付与することによって指定される。暗号化鍵は、カレントのセッションステータスによって決定される ( 6.1 章 を参照のこと)。

デジタル署名においては、署名アルゴリズムへの入力として、一方向ハッシュ関数の出力を使用する。デジタル的に署名された要素は、opaque ベクトル <0..2^16-1> としてエンコードされる。その長さは、署名アルゴリズムと鍵によって特定される。

RSA 署名においては、2 つのハッシュ値(1つは SHA、もうひとつは MD5)をもつ、 36 バイトの構造体に署名する(秘密鍵により暗号化される)。これは、[PKCS1] に示されている、PKCS #1 ブロック型 0 または ブロック型 1 によりエンコードされる。

DSS においては、SHA によりハッシュされた 20 バイトのデータが、さらにハッシュ処理されることなく、デジタル署名アルゴリズム(DSA) に直接渡される。これにより 2 つの値、r と s が生成される。DSS 署名は、上記のように opaque ベクトルであり、その内容を DER エンコードで示すと、以下のようになる。

Dss-Sig-Value ::= SEQUENCE {

r INTEGER,
s INTEGER

}

ストリーム暗号では、平文は、暗号学的にセキュアな擬似乱数発生器により生成された、平文と同じ量の出力と、排他的ORの演算が行なわれる。

ブロック暗号では、それぞれの平文ブロックは、ひとつの暗号文ブロックに暗号化される。すべてのブロック暗号は、CBC (Cipher Block Chaining) モードで処理される。ブロック暗号処理されたすべてのブロックは、暗号ブロック長の整数倍となる。

公開鍵暗号では、公開鍵アルゴリズムを使用してデータを暗号化するため、その公開鍵に対する秘密鍵を使用してのみ、データを復号することができる。公開鍵暗号で暗号化された要素は、opaque 型のベクトル<0..2^16-1> としてエンコードされる。ここで、要素の長さは、署名アルゴリズムと鍵により特定される。
RSA 暗号値は、[PKCS1] で示されている、PKCS #1ブロック型 2 でエンコードされる。

例えば次の例では、

stream-ciphered struct {

uint8 field1;
uint8 field2;
digitally-signed opaque hash[20];

} UserType;

hash の内容が、署名アルゴリズムへの入力として使用される。そして、構造体全体がストリーム暗号で暗号化される。この構造体の長さは、field1 と field2 のための 2 バイト、署名の長さのための 2バイト、および署名アルゴリズムの出力長を加えた長さ(バイト数)である。構造体をエンコードまたはデコードする前に、署名に使用されるアルゴリズムと鍵がわかっているので、この長さは既知である。

 

4.8. 定数 English

必要な型を宣言し値をそれに割当てることにより、型をもつ定数を定義することができる。特定の型(opaque、可変長ベクトル、および opaque を含む構造体)に値を割り当てることはできない。複数の要素を持つ構造体またはベクトルでは、フィールドを省略することはできない。

例:

struct {

uint8 f1;
uint8 f2;

} Example1;
Example1 ex1 = {1, 4}; /* f1 = 1, f2 = 4 の割り当て */


3<- 目次 ->5