PERは 「可能な限り単純な符号化規則を使って最も簡潔な符号を得る」ものです。 BERのタグ・長さ・値のTLV3項組みの代わりに、 PERはプリアンブル(複数又は省略される場合あり)、 長さ(省略される場合あり)、値(省略される場合あり)のPLVからなります。
オクテット列ではなく原則ビット列です。 各要素は次の種類があります。
BERでは個別メッセージのASN.1仕様を知らなくてもタグと長さを使ってある程度の復号が可能ですが、 PERは長さや値のフィールドがオプション(必要な場合にのみ指定)で、 ASN.1仕様で指定された各種制限に依存して符号化するため、 符号化と復号化にはASN.1仕様の参照が必要です。 BERでは、タグで区別することで、容易にCHOICEやSETやSEQUENCEに要素を追加する拡張が可能でしたが、 PERはタグがないので拡張性は事前に計画しておく必要があります。 拡張が指定されている場合、プリアンブルに拡張の有無を示すビットが設定されます。 長さはASN.1仕様のSIZE制約で固定長になっていいる場合、一部例外を除き、符号化されません。 SEQUENCEやSETの値の符号化は、オプション要素(OPTIONALやDEFAULT)の存在や非存在を示すプリアンブルで始まります。 CHOICEは選択肢を示すインデックスから始まります。
一般に、PERで符号化は初期処理が大きいがエンコードとデコードは静的でBERより早く、 BERよりサイズが小さいのでネットワーク転送が早くなります。
PERは2つ形式があります: 基本形式(BASIC-PER)と正規化形式(CANONICAL-PER)です。 そしてそれぞれ整列(ALIGNED)と非整列(UNALIGNED)があります。
正規化形式は基本形式に制限を加えたものです。 この形式はリレーシステムやディジタル署名に適用されます。 基本形式で、値はいくつもの符号化形式をもつかもしれません。 他方、検査は限定されるので、基本形式コーダは正規化コーダより速いでしょう。
整列形式はオクテット境界にそろえるために必要なら、0のビットが挿入されます。 非整列形式でオクテット境界はなく、すべてのビットが使われます。 非整列形式はコンパクトですが、符号化と復号化により時間がかかる処理を必要とします。 整列と非整列は互換性が無く、整列形式デコーダは非整列形式をデコードできません。
符号化する整数をnとします。 整数の範囲に制限がある場合、つまり最小値MINと最大値MAXが決まっている場合、値(n-MIN)を符号化します。 特にMIN=MAXの場合は、値が明らかなので符号化しません(=省略)。 なお、以下の2進形式は、第iビットが2^iを示す一般的な符号なし2進形式です。
SEQUENCEやSETの拡張ビットマップの大きさやCHOICEのインデックスは整数で、 一般に小さいが制限がない事も多いので、「通常小さい非負整数形式」が使われます。 符号化する整数をnとします。
整数nの下限MINは有限であるが上限が+∞の場合の符号化です。 可変長扱いになります。 (n-MIN)の符号化に必要最小なオクテット数L(=log256(n-MIN)、小数点以下切上げ)を符号化し、 この後にLオクテットの符号なし2進法の形式で符号化したフィールドが続きます。 非整列形式ではフィールドはオクテット整列をしない非整列ビットフィールドで、 整列形式ではフィールドはオクテット整列をする整列ビットフィールドになります。 Lのフォーマットは後記の通りです。
整数の範囲に制限がない場合は、符号付き整数でnを符号化します。 可変長扱いになります。 符号化に必要最小なオクテット数Lを符号化し、 この後にLオクテットの符号付き2進法の形式(2の補数表現)で符号化したフィールドが続きます。 非整列形式ではフィールドはオクテット整列をしない非整列ビットフィールドで、 整列形式ではフィールドはオクテット整列をする整列ビットフィールドになります。 Lのフォーマットは後記の通りです。
BERでは長さフィールドは常に存在し、オクテット単位でしたが、 PERでは長さフィールドは必要な場合にだけ存在します。 BERでは長さはオクテット単位でしたが、PERではビット列ではビット単位、 オクテット列(OCTET STRINGやオープン型)ではオクテット単位、文字列は文字数、 SEQUENCE OFやSET OFでは要素数を表します。 ASN.1仕様によって、長さlenの下限(0以上)と上限(∞かもしれない)が存在し、 これによって長さlenの符号化は影響を受けます。
オープン型は、ASN.1の符号化あるいはその他の方法で符号化された後、 長さに制限がないオクテット列の様に扱われ、長さL(単位はオクテット)と、 それに続くオクテット列として符号化されます。 整列形式ではオクテット整列が行われます。
1ビットの非整列ビットフィールドで符号化します。 TRUEの値は1で、FALSEの値は0です。 長さLは使いません。
以下の制約を考慮し、整数の上限下限を決定します。
例:Two ::= INTEGER (2)
例:From3to15 ::= INTEGER (3..15) 例:PositiveOrZeroNumber ::= Number (0..MAX)
整数型の符号化は以下の通りです。
@もし、拡張マークが指定されるなら、プリアンブルとして1ビットの非整列ビットフィールドを符号化します。 値が、元々定義された範囲であれば非整列ビットフィールドの値は0で、範囲外(拡張された値)であれば値は1です。 値が0の場合はAへ、拡張した値の場合はDへ進みます。 なお、整数型の符号化では整数の上限と下限だけを考えているため、 拡張した値であっても元の上限と下限の範囲内にあれば、拡張されていない値と扱います。
Aもし、制約条件が値を1つに制限するなら、値を符号化せず(=長さLや値Vは省略)、手順を終了します。
Bもし、制約条件が値の範囲を制限するなら、有限範囲の整数として符号化し、手順を終了します。
Cもし、制約条件が値の下限を示すなら、部分制限整数として符号化し、手順を終了します。
D値を制限なしの整数で符号化し、手順を終了します。
拡張マークなし | 拡張マーク有り | ||
拡張なしの値範囲 | 拡張した値範囲 | ||
値は固定値 | 符号化しない | ||
値は有限範囲 | |||
値の下限あり | |||
値の制限なし |
列挙型の符号化は以下の通りです。
@もし拡張マークが指定されるなら、プリアンブルとして、1ビットの非整列ビットフィールドを符号化します。 値が、最初に定義された範囲であれば非整列ビットフィールドの値は0で、 範囲外(拡張された値)であれば値は1です。 値が0の場合はAへ、拡張した値の場合はBへ進みます。
A列挙型の要素を要素値の順番に並べ、0から順に番号を振り直します (元の要素値が飛び飛びでも間を詰めて番号を振りな直します)。 番号を、最小値は0で最大値は最後の要素の番号の有限範囲の整数として符号化し、手順を終了します。
B非拡張の要素を除き、列挙型の要素を要素値の順番に並べ、0から順に番号を振り直します。 この時、より新しい要素はより後に並べます。番号を、 通常小さい非負整数 として符号化し、手順を終了します。
拡張マークなし | 拡張マーク有り | |
拡張なしの値範囲 | 拡張した値範囲 | |
実数型の符号化はCER/DERとほぼ同じです。 CER/DERにおける実数の符号化値がlenオクテットとします。 長さL=lenをまず符号化し、続いてCER/DER符号化の値(タグや長さを除く)を符号化します。 後者は、整列形式であればオクテット整列し、非整列形式であれば整列しません。
以下の制約を考慮します。
例:Exactly31BitsString ::= BIT STRING (SIZE (31)) 例:StringOf31BitsAtTheMost ::= BIT STRING (SIZE (0..31))
ビット列型の符号化は以下の通りです。
@もし、名前つきビット列型であれば、ビット列の後ろの不要な0は削除されます。
Aもしサイズ制約条件があるなら、サイズ制約条件を満たす範囲で、長さが最小になるように、 ビット列の最後に0を追加したり、ビットを削除したりします。
Bもし、サイズ制限に拡張マークがあるなら、プリアンブルとして、 1ビットの非整列ビットフィールドを符号化します。 値が、最初に定義された範囲であれば非整列ビットフィールドの値は0で、 範囲外(拡張された値)であれば値は1です。 値が0の場合はCへ、拡張した値の場合はFへ進みます。
Cもし、サイズの上限がゼロなら、ビットは存在しないので、 符号化せず(=長さLや値Vは省略)、手順を終了します。
Dもし、サイズが固定長(サイズ下限=サイズ上限)で16ビット以下なら、 ビット列は長さなしで、指定された長さで符号化し、手順を終了します。オクテット整列をしません。
Eもし、サイズが固定長(サイズ下限=サイズ上限)で17ビット以上65536ビット以下なら、 ビット列は長さなしで、指定された長さで符号化し、手順を終了します。 整列形式の場合はオクテット整列をします。
Fビット列の長さLビットを、制限整数(サイズ上限が有限の場合)、 または、部分制限整数(拡張された値やサイズ上限が無限の場合)で符号化します。 続いて長さLビットのビット列を符号化します。
長さに拡張マークなし | 長さに拡張マーク有り | ||
拡張なしの値範囲 | 拡張した値範囲 | ||
長さ0 | 符号化しない | ||
固定長(65536ビット以下) | |||
その他 |
以下の制約を考慮します。
例:NonEmptyString ::= OCTET STRING (SIZE (1..MAX))
オクテット列型の符号化は以下の通りです(単位が違う以外は、ビット列型と同様です)。
@もしサイズ制限があり、拡張マークが存在するなら、プリアンブルとして、 1ビットの非整列ビットフィールドを符号化します。 値が、最初に定義された範囲であれば非整列ビットフィールドの値は0で、 範囲外(拡張された値)であれば値は1です。 値が0の場合はAへ、拡張した値の場合はCへ進みます。
Aもし、サイズの上限がゼロなら、オクテットは存在しないので、 符号化せず(=長さLや値Vは省略)、手順を終了します。
Bもし、サイズが固定長(サイズ下限=サイズ上限)で2オクテット以下なら、 オクテット列は長さなしで、指定された長さで符号化し、手順を終了します。 オクテット整列をしません。
Eもし、サイズが固定長(サイズ下限=サイズ上限)で2オクテット以上65536オクテット以下なら、 オクテット列は長さなしで、指定された長さで符号化し、手順を終了します。 整列形式の場合はオクテット整列をします。
Cオクテット列の長さLオクテットを、制限整数(サイズ上限が有限の場合)、または、 部分制限整数(サイズ上限が無限の場合)で符号化します。 続いて長さLオクテットのオクテット列を符号化します。
符号化しません。 ヌル型は実質的には、選択型での選択肢がない場合や、集合型と順序列型のオプション要素の、穴埋めで使われます。 プリアンブルがあるので選択型でのヌルの選択や、オプション要素は、ヌルのオクテット表現なしで実行できます。
@もし順序列型に拡張マークが存在するなら、プリアンブルとして、1ビットの非整列ビットフィールドを符号化します。 追加された要素が存在しなければ非整列ビットフィールドの値は0で、追加された要素が存在すれば値は1です。
Aもし、拡張要素を除き、順序列型の中にOPTIONALかDEFAULTと指定された要素がn個存在するなら、 プリアンブルとして、nビットのビットフィールドを符号化します。 オクテット整列をしません。 nビットの各ビットは、OPTIONALかDEFAULTの要素が存在するか否かを示します。 存在すれば1で、存在しなければ0で符号化します。 先頭ビットが順序列型の中の最初のOPTIONALかDEFAULTの要素の存在を示します。 なお、nが65537以上の場合は符号化方法が少し変わりますが、ここでは省略します。
Bプリアンブルに続いて順序列型の、拡張要素を除く各要素を、順番にそれぞれの型の符号化方法で符号化します。 OPTIONALかDEFAULTの要素で存在しないものは符号化しません。
C正規化形式で、DEFAULTと指定された要素は値がデフォルト値に一致する場合には、常に符号化しません。 基本形式で、DEFAULTと指定された要素は単純型で値がデフォルト値に一致する場合には、常に符号化しません。 構造型の場合は、符号化するかどうかはコーダの任意です。
D拡張要素が存在しない場合は、ここで符号化は終了します。
E拡張要素の数nを、「通常小さい非負整数」で符号化します。 (もしかしたら、nでなくn-1を符号化するかもしれない・・・)
F続いて、nビットのビットフィールドを符号化します。 nビットの各ビットは拡張要素が存在するか否かを示します。 存在すれば1、存在しなければ0です。 なお、2重鍵括弧で囲まれた一群の要素は、一群の要素全体が1つのSEQUENCE要素であるかの様に扱います。
G続いて、存在する拡張要素を順番に順番に符号化します。 符号化は、それぞれの型の符号化方法で符号化したものを、オープン型の値として符号化します。
拡張マーク | 拡張 | |
なし | − | |
あり | なし | |
あり | あり |
以下の制約を考慮します。
例:ListOf5Strings ::= SEQUENCE (SIZE (5)) OF PrintableString 例:ListOf5StringsOf5Characters ::=SEQUENCE (SIZE (5)) OF PrintableString (SIZE (5))
@もし、サイズ制限が拡張可能であれば、プリアンブルとして、1ビットの非整列ビットフィールドを符号化します。 サイズが元々指定された範囲内であれば非整列ビットフィールドの値は0で、範囲外であれば値は1です。 値が0の場合はAへ進みます。 拡張した値の場合は要素数nを部分制限整数で符号化します。 続いてn個の要素を符号化し、手順を終了します。
Aもし、サイズ制限で要素数nが固定長(サイズ下限=サイズ上限)で65536個以下なら、 要素数nは符号化せず、n個数の要素を符号化し、手順を終了します。
B要素数nを、制限整数(サイズ上限が有限の場合)または部分制限整数(サイズ上限が無限の場合)で符号化します。 続いてn個数の要素を符号化し、手順を終了します。
長さに拡張マークなし | 長さに拡張マーク有り | ||
拡張なしの値範囲 | 拡張した値範囲 | ||
要素が0個 | 符号化しない | ||
固定個(65536個以下) |
|
||
その他 |
集合型を符号化する場合、要素の順序を正規化し、SEQUENCE型と同じ符号化をします。 [拡張されていない要素は、タグ順に並べます。 タグの順序とは汎用、応用、文脈特定、私用のクラス順で、 同じクラスではタグの数字が小さいものが先、大きいものが後になります。 要素がタグなしのCHOICE型の場合、CHOICE型要素のテキストで最初に記述されている要素のタグ値を持つと考えます。 拡張要素はASN.1仕様のテキストの記述順序で並べます。
以下の制約を考慮します。
正規化形式では、要素は上昇順で並べられます。比較は各要素をビット列として比較します。
符号化はSEQUENCE OF型と同様です。
@もし、選択型に拡張マークが存在するなら、プリアンブルとして、 1ビットの非整列ビットフィールドを符号化します。 サイズが元々指定された範囲内であれば非整列ビットフィールドの値は0で、範囲外であれは1です。
A選択型に複数の選択肢がある場合、 どの要素が選択されたかを示すインデックス値(最小値0、最大値は選択肢の数−1)を符号化します。 拡張されていない要素のインデックス値は、要素をタグ順に並べ、先頭を0として、 順番に番号を振ったものです。 タグの順序とは汎用、応用、文脈特定、私用のクラス順で、 同じクラスではタグの数字が小さいものが先、大きいものが後になります。 要素がタグなしの選択型の場合、選択型要素のテキストで最初に記述されている要素のタグ値を持つと考えます。 拡張要素のインデックス値はASN.1仕様のテキストの記述順序で並べ、先頭を0として、順番に番号を振ったものです。 インデックス値の符号化方法は、拡張されていない要素の場合整数型で、 拡張要素の場合は、通常小さい非負整数で符号化します。選択型の選択肢が1つしかなければ、 インデックス値の符号化はしません。
B最後に要素を符号化します。 拡張されていない要素はそのまま符号化し、拡張要素は、オープン型の値として符号化します。
拡張マークなし | 拡張マーク有り | ||
拡張なしの要素 | 拡張した要素 | ||
選択肢が1個 | (ありえない?) | ||
その他 |
符号化後のオクテット数Lに続いて、値をBERの値と同じ方法で符号化します。
以下の制約を考慮します。
例:Morse ::= PrintableString (FROM ("."|"-"|" ")) 例:IDCardNumber ::=NumericString (FROM ("0".."9")) 例:PushButtonDialSequence ::=IA5String (FROM ("0".."9"|"*"|"#"))
例: LongWeekEnd ::= Day (WeekEnd|monday)
@基本的に文字数Lに続いて文字列を符号化します。
A各文字は最少ビット数で符号化します。 非整列型の場合、FROM制約の適用によって使用可能な文字数がNであれば、 log2(N)ビット(小数点以下切上げ)で符号化します。 整列型の場合、log2(N)より大きい、2の累乗になるビット長 (つまり、1ビット、2ビット、4ビット、8ビット、16ビット・・・)で符号化します。 各文字の対応する値は、各文字の値を小さい順に並べて、0らか順に値を振りなおしたものです。 但し、FROM制約が拡張可能であれば、FROM制約はないものとみなします (元となる型の全ての文字が使えると考えます)。
Bもしサイズ制限があり、拡張マークが存在するなら、プリアンブルとして、 1ビットの非整列ビットフィールドを符号化します。 値が、最初に定義された範囲であれば非整列ビットフィールドの値は0で、 範囲外(拡張された値)であれば値は1です。 値が0の場合はCへ、拡張した値の場合はEへ進みます。
Cもし、サイズが固定長(サイズ下限=サイズ上限)で、 符号化した文字列が2オクテット以下なら、 文字列は長さなしで、指定された長さで符号化し、手順を終了します。 オクテット整列をしません。
Dもし、サイズが固定長(サイズ下限=サイズ上限)で符号化した文字列が2オクテット以上65536文字以下なら、 ビット列は長さなしで、指定された長さで符号化し、手順を終了します。 整列形式の場合はオクテット整列をします。
E文字列の長さL文字を、 制限整数(サイズ上限が有限の場合)または部分制限整数(サイズ上限が無限の場合)で符号化します。 続いて長さL文字の文字列を符号化します。