轉自: http://wmfbravo.blog.163.com/
感謝: wmfbravo
3 編碼規則和傳輸語法
本章主要介紹BER和PER兩種編碼規則及其衍生規則。
3.1 BER
3.1.1 基本規則
BER(Basic Encoding Rules)是ASN.1中最早定義的編碼規則,在討論詳細編碼規則時,我們是基於正確的抽象描述上。BER傳輸語法的格式一直是TLV三元組<Type, Length, Value>也可以認為是<Tag, Length, Value>,見Figure 3-1。TLV每個域都是一系列八位組,對於組合結構,其中V還可以是TLV三元組,見Figure 3-2。BER傳輸語法是基於八位組(為了避免不同系統上的混淆,沒有采用Byte為單位)的,自定界的編碼,因為其中L明確界定了八位組的長度。BER是大端編碼的,其八位組的高位比特在左手邊,見Figure 3-3。
BER編碼中的Tag(通常是一個八位組),指明了值的類型,其中一個比特表征是基本類型還是組合類型。Tag有如下兩種形式:
Figure 3-4 Tag的兩種形式
當Tag不大於30時,Tag只在一個八位組中編碼;當Tag大於30時,則Tag在多個八位組中編碼。在多個八位組中編碼時,第一個八位組后五位全部為1,其余的八位組最高位為1表示后續還有,為0表示Tag結束。Tag的值需要將上圖中黃色部分拼接后才能得到。
BER編碼中Length表示Value部分所占八位組的個數,有兩大類:定長方式(Definite Form)和不定長方式(Indefinite Form);在確定方式中,按照Length所占的八位組個數又分為短、長兩種形式。具體如下:
Figure 3-5 Length的三種形式
采用定長方式,當長度不大於127個八位組時,Length只在一個八位組中編碼;當長度大於127時,在多個八位組中編碼,此時第一個八位組低七位表示的是Length所占的長度,后續八位組表示Value的長度。
采用不定長方式時,Length所在八位組固定編碼為0x80,但在Value編碼結束后以兩個0x00結尾。這種方式使得可以在編碼沒有完全結束的情況下,可以先發送部分消息給對方。
BER編碼規則的Object Identifier注冊為{joint-iso-itu-t(2) asn1(1) base-encoding(1)},其Object Description為“"Basic Encoding of a single ASN.1 type”。
3.1.2 各類型的編碼
本小節中以UNIVERSAL Tag和短型Value為例,討論各種類型的BER編碼,重點關注Value部分。在舉例中,n10表示數字n是十進制數。
I. BOOLEAN
只能以primitive方式編碼。
FALSE的編碼為:
Figure 3-6 BOOLEAN: FALSE的編碼
TRUE的編碼(任何不是全0都可以)為:
或者:
Figure 3-7 BOOLEAN: TRUE的編碼
II. NULL
只能以primitive方式編碼,且只有一個值:
Figure 3-8 NULL的編碼
III. INTEGER
只能以primitive方式編碼。
我們分編、解碼兩個過程,正數、負數兩種情況來討論。
1) 編碼過程:
Figure 3-9 INTEGER編碼過程
l 對於正數,如果最高比特位為0則直接編碼;如果為1,則在最高比特位之前增加一個全0的八位組。
l 對於負數,先取絕對值,再取反,最后加1。
2) 解碼過程:
Figure 3-10 INTEGER解碼過程
基於前面所述的規則,整數-27,066的編碼為:
Figure 3-11 整數-27,066的編碼
IV. ENUMERATED
ENUMERATED的值按照前面整數值的規則編碼。
V. REAL
Figure 3-12 REAL類型編碼
VI. BIT STRING
可以primitive方式編碼或者constructed方式編碼。
采用primitive方式,對'1011011101011'B的編碼規則如下:
Figure 3-13 BIT STRING: '1011011101011'B的primitive form編碼
注意在'1011011101011'B前增加了一個八位組,取值為0到7,表征這個值最后補位的個數。由發送方決定補位采用0還是1。
如果BIT STRING的值為空,則編碼時,長度為1,補充的八位組為全0。
Figure 3-14 BIT STRING值為空的編碼
constructed方式是在發送時,有部分編碼還不能確定時采用的,前一個值的編碼如下:
Figure 3-15 BIT STRING: '1011011101011'B的constructed form編碼
注意Length部分采用的是不定長編碼。
VII. OCTET STRING
與BIT STRING類似,但是不需要增加表征補充位個數的八位組。
VIII. OBJECT IDENTIFIER
只能以primitive方式編碼。
編碼時,第一個八位組采用公式:first_arc * 40+second_arc。
Table 3-1 OBJECT IDENGTIFIER第一個八位組解碼
對{iso member-body f(250) type-org(1) ft(16) asn1-book(9)}的編碼為:
Figure 3-16 OBJECT IDENTIFIER編碼示例
注意對250的編碼方式。
IX. RELATIVE-OID
與OBJECT IDENTIFIER類似,但是不需要對注冊樹前兩段進行特殊處理。對{f(250) type-org(1) ft(16) asn1-book(9)}的編碼為:
Figure 3-17 RELATIVE-OID編碼示例
X. 字符串和日期
和OCTET STRING編碼類似,只是Tag不同。
XI. SEQUENCE
肯定時constructed形式的。
在編碼SEQUENCE時,其每個成員都要以TLV三元組方式編碼,而且順序要與SEQUENCE定義的一致。對於標記為DEFAULT的成員,即使發送方應用層給出了值,也是有發送者決定是否對該成員進行編碼。
對如下定義:
v SEQUENCE { age INTEGER, single BOOLEAN } ::=
{ age 24, single TRUE }
的編碼為:
Figure 3-18 SEQUENCE編碼示例
如果SEQUENCE定義中包括擴展符,則省略;如果有擴展的成員則編碼。
XII. SET
與SEQUENCE類似,但是成員順序有發送者決定。
XIII. SEQUENCE OF
SEQUENCE OF的Tag與SEQUENCE相同,編碼規則也相同。
對定義為:
triplet SEQUENCE OF INTEGER ::= {2, 6, 5}
的編碼為:
Figure 3-19 SEQUENCE OF編碼示例
XIV. SET OF
與SEQUENCE OF類似。
XV. CHOICE
嚴格說CHOICE類型在編碼中並不存在,只是在描述中體現一種關系。編碼時,是按照具體被選擇的成員編碼規則編碼的。
對定義為:
famous CHOICE { name VisibleString, nobody NULL } ::= name:"Perec"
的編碼為:
Figure 3-20 CHOICE編碼示例
如果CHOICE類型顯式(EXPLICIT)指定了Tag,那么該Tag應當以constructed方式編碼,具體在XVI. 中討論。
如果CHOICE類型包含有擴展符則忽略;如果有擴展成員則編碼。
XVI. Tagged Value
如果一個類型的Tag是隱式(IMPLICIT)的(或者在模塊定義中聲明了IMPLICIT TAGS或者AUTOMATIC TAGS),則只有出現在關鍵字IMPLICIT左側的Tag才會被編碼。
如定義:
v [1] IMPLICIT INTEGER ::= -38
的編碼為:
Figure 3-21 IMPLICIT TAG編碼示例
如果一個類型的Tag是顯式(EXPLICIT)的(或者在模塊定義中聲明了EXPLICIT TAGS),則要以constructed方式編碼三元組系列。
如定義:
v [APPLICATION 0] EXPLICIT INTEGER ::= 38
的編碼為:
Figure 3-22 EXPLICIT TAG編碼示例
注意第一個Tag是APPLICTION、constructed方式,Length是后續八位組的長度。
XVII. 子類型約束
因為子類型約束是在BER編碼規則之后被引入ASN.1的,所以在編碼規則中不能體現約束。
XVIII. EXTERNAL
該類型不推薦使用,略。
XIX. INSTANCE OF
定義為:
v INSTANCE OF TYPE-IDENTIFIER ::=
{
type-id {iso member-body f(250) type-org(1) ft(16) asn1-book(9)
chapter18(5) integer-type(0)},
value INTEGER:5
}
的編碼應當和如下一個SEQUENCE類型的值相同:
{ direct-reference {iso member-body f(250) type-org(1) ft(16) asn1-book(9)
chapter18(5) integer-type(0)},
encoding single-ASN1-type:INTEGER:5 }
編碼為:
Figure 3-23 INSTANCE OF的編碼示例
XX. EMBEDDED PDV
EMBEDDED PDV的編碼和其等效的SEQUENCE結構編碼類似。其嵌入部分的編碼,應該是遵循identification成員指定的規則。
XXI. CHARACTER STRING
CHARACTER STRING的編碼和其等效的SEQUENCE結構編碼類似。其嵌入字符串部分的編碼,應該是遵循identification成員指定的規則。
XXII. Information Objects and Object Sets
信息對象和對象集合永遠都不編碼。如前所述,傳遞他們所包含信息的途徑是在值定義或者類型定義中引用他們。這樣的結果,不是在編碼中出現了這些信息,而是ASN.1編譯器在生成編解碼器時,會按照這些信息生成相應的約束表。
XXIII. Value Set
值集合的編碼按照對應類型的編碼規則進行。
3.1.3 BER編碼規則的屬性
l BER編碼規則是機器無關的:通訊應用可以很容易支持大端和這種編碼格式;而且能支持各種不同的整數長度。
l BER的傳輸語法是十分冗長的:T和L很多情況下都是可以省略的,但是這種冗余信息一些情況下也有顯著的優勢,它能很好的保藏抽象語法結構,BER傳輸語法能容易升級而且向上兼容。如每個類型都可以用CHOICE來代替:
T ::= IA5String -- old version
可以更新為:
T ::= CHOICE {
iA5String IA5String,
universalString UniversalString } -- new version
當舊的解碼器收到universalString時,它可以明確知道收到的不是iA5String,而且知道具體長度,可以很容易忽略這個信元。
在此基礎上,可以看出,BER規則中SEQUENCE、SET都是缺省可擴展的。另外,對ENUMERATED,BER也沒有對邊界進行限定,因此也是可擴展的。
當整個抽象語法都是顯式(EXPLICIT)Tag時,解碼器能在不了解具體抽象語法的情況下解碼,能以更為用戶友好的方式展示結果。如對BOOLEAN類型顯示為“TRUE”或者“FALSE”而不是碼字。
置於長度,如果系統性的使用長度,可以根據使用情況更為有效傳遞,而不用嚴格傳輸諸如SIZE(200)。
當然,BER的優勢在某些方面也成了不足之處,這也導致了其它編碼規則的產生。
3.1.4 一個完整的例子
這里,以一個HTTP的片段作為示例:
MyHTTP DEFINITIONS AUTOMATIC TAGS ::=
BEGIN
GetRequest ::= SEQUENCE
{
header-only BOOLEAN,
lock BOOLEAN,
accept-types AcceptTypes,
url Url,
...
}
AcceptTypes ::= SET
{
standards BIT STRING {html(0), plain-text(1), gif(2),
jpeg(3)} (SIZE (4)) OPTIONAL,
others SEQUENCE OF VisibleString (SIZE (4))
OPTIONAL
}
Url ::= VisibleString (FROM ("a".."z"|"A".."Z"|"0".."9"|"./-_~%#"))
v GetRequest ::=
{
header-only TRUE,
lock FALSE,
accept-types { standards {html,plain-text} },
url "www.asn1.com"
}
END
值v對應的BER編碼結果為:
Figure 3-24 BER編碼示例