ASN.1
在通信和計算機網絡領域,ASN.1(Abstract Syntax Notation One) 是一套標準,用於描述數據類型的表示、編碼、傳輸、解碼。提供了一套形式(formal)、無歧義和精確的規則以描述獨立於特定計算機硬件的數據類型和多種編碼表示。[1]ASN.1是一種和平台、語言無關的描述語言。用於跨平台編程的protocol buffers和Apache Thrift具有類似功用。
最初是1984年的CCITT X.409:1984的一部分。由於其廣泛應用,1988年ASN.1移到獨立標準X.208,1995年進行全面修訂後變成X.680系列標準。
ASN.1本身只定義了表示信息的抽象句法,但是沒有限定其編碼的方法。各種ASN.1的編碼規則提供了由ASN.1描述其抽象句法的數據的值的傳送語法(具體表達)。標準的ASN.1編碼規則有:
- 基本編碼規則(BER,Basic Encoding Rules)
- 規範編碼規則(CER,Canonical Encoding Rules)
- 唯一編碼規則(DER,Distinguished Encoding Rules)
- 壓縮編碼規則(PER,Packed Encoding Rules)
- XML編碼規則(XER,XML Encoding Rules)
給定了協議內容並選定了編碼規則,很多工具可以生成讀(解碼)寫(編碼)PTU的C/C++、Java、C#、Python等原始碼。
基本概念
編輯在ASN.1中,符號的 定義沒有先後次序,只要能夠找到該符號的定義。即可先使用後定義。例如:
age Age ::= 18 创建Age的实例 Age ::= INTEGER 定义了Age这个类型
標識符、參考、關鍵字都要以一個字母開頭,後接字母、數字或者連字符『-』 (而不是下劃線)。同時不能以連字符結尾,也不能連續出現兩個連字符。
關鍵字全部大寫。
在標識符中,只有類型和模塊名字是以大寫字母開頭的,其他標識符都是以小寫字母開頭
註釋以兩個連字符「–」開始,結束於行的末尾或者該行中另一個雙連字符
ASN.1的數據類型
編輯基本類型
編輯- NULL 值NULL,用於傳送一個報告或者作為CHOICE類型中的值 null
- INTEGER 整數類型 int/Integer
- REAL 浮點數 double/Double/Float/float
- ENUMERATED 標識符的枚舉
- BITSTRING 比特串 字節的位表示方法,可以給一個byte中的每一個bit進行設值
- OCTETSTRING 字節串 8進制表示的字符串
- OBJECT IDENTIFIER或RELATIVE-OID 一個實體的標識符
- EXTERNAL,EMBEDDED PDV 表示層上下文交換類型
- NumericString
- PrintableString
- VisibleString:ASCII表去除控制字符。
- UTF8String
- ISO64String
- IA5String 實際上是ASCII表的前128個字符。ITU-T recommendation T.50 specifies the International Reference Alphabet (IRA), formerly International Alphabet No. 5 (IA5), a character encoding.
- TeletexStirng
- T61String
- VideotexString
- GraphicString
- GeneralString
- UniversalString
- BMPString
- UTF8String
- CHARACTERSTRING 允許為字符串協商一個明確的字符表
- UTCTime
- GeneralizedTime
- DATE 表示日期,格式是"YYYY-MM-DD":
- TIME-OF-DAY 表示日期中的時間,格式是"HH:MM:SS":
- DATE-TIME 時間加日期的格式,它的格式"YYYY-MM-DDTHH:MM:SS"
- BOOLEAN 有兩個可能得值:TRUE和FALSE。
組合類型
編輯- CHOICE 選擇類型,該字段可能有多重不同的類型來表示,相當於C語言的union
- SEQUENCE 由不同類型的值組成一個有序的集合
- SET 無序集合(不同類型的值)
- SEQUENCEOF 由相同類型的值組成一個有序的集合
- SETOF 無序集合(相同類型的值)
子類型
編輯子類型(subtype)的值集合是其父類型值集合的子集。
單一值,即在定義中列舉出所有可能的取值:
TestResult ::=INTEGER(1|2|3|4) sp1 TestResult ::= 2 Colors ::= UTF8String ("Blue" | "White")
SIZE關鍵字指示字符串的長度:
WorkstationNumber::=OCTET STRING(SIZE(6)) BitField ::= BIT STRING(SIZE(12)) map1 BitField ::= "100110100100"B map2 BitField ::= "9A4"H
SIZE關鍵字也可指示數組的長度:
Name ::= IA5String (SIZE (4..7)) NameList ::= SEQUENCE SIZE (1..25) OF Name
使用..可以表示一個範圍(range)。只適用於整數和實數類型:
NoID::=INTEGER(1..100) PositiveInteger ::=INTEGER(0..MAX) PositiveInteger ::=INTEGER(1..MAX)
FROM關鍵字用於限制字符集的取值範圍。只適用於字符串類型:
DigitString ::=IA5String((2)|(3)|(4)|5|(6)|(7)) str2 DigitString ::= "46732" PermittedChars ::= IA5String (FROM("ABCDEFG1244"))
PATTERN關鍵字指示正則表達式:
phoneNumber ::= IA5String (PATTERN "1[0-9]#10")
內部類型(Inner Subtyping)。適用於SEQUENCE,SEQUENCE OF,SET,SET OF和CHOICE類,主要用於對這些結構類型的元素項進行限制:
PDU::=set{ alpha [0] INTEGER, beta [1] IA5striong OPTIONAL, gamma [2] SEQUENCE OF parameter, delta [3] BOOLEAN } TestPDU::=PDU(WITH COMPONENTS{ alpha(min..<0),...,delta(FALSE) })
枚舉子類型,說明被定義的新子類型包含原子類型的全部可能值。
Months::=ENUMERATED{ jaunary(1), february(2), ..., december(12) } First-quarter::=Months(january,february,march); Second-quarter::=Months(april,may,june) First-half::=Months (INCLUDES First-quarter|INCLUDE Second-quarter) jan First-quarter ::= 1
類型的定義及賦值
編輯<新类型的名字>::= <类型描述> <新类型的名字>是一个类型的名字,也可以是类型描述 <类型描述>基本类型、组合类型 <新的值的名字><该值的类型> ::= <值描述> <新的值的名字>是以小写字母开头的标识符; <该值的类型>可以是一个类型的名字,也可以是类型描述; <值描述>是基于整数、字符串、标识符的组合
ASN.1信息對象類和信息對象
編輯信息對象類用於表達比註釋更為正式的一些信息。
<信息对象类>::= CLASS <类描述> WITHSYNTAX <信息描述> <模块名字> DEFINITIONS <缺省Tag>::= BEGIN EXPORTS <导出描述> IMPORTS <导入描述> <模块体描述> END IMPORTS <名字>,value FROM <其它模块的ObjectIdentifier>; EXPORTS<名字>;
例如:
--<ASN1.HugeInteger World-Schema.Rocket.range>-- World-Schema DEFINITIONS AUTOMATIC TAGS ::= BEGIN Rocket ::= SEQUENCE { range INTEGER, -- huge (see a special directive above) name UTF8String (SIZE(1..16)), message UTF8String DEFAULT "Hello World" , fuel ENUMERATED {solid, liquid, gas}, speed CHOICE { mph INTEGER, kmph INTEGER } OPTIONAL, payload SEQUENCE OF UTF8String } END
Module2 { isomember-body(2) f(250) type-org(1) ft(16) asn1-book(9)chapter5(0) module2(1) } DEFINITIONS AUTOMATIC TAGS ::= BEGIN EXPORTS Type2; IMPORTS Type1, value FROM Module1 {iso member-body(2) f(250) type-org(1)ft(16) asn1-book(9) chapter5(0) module1(0)}; Type2 ::= SEQUENCE OF Choice Choice ::= CHOICE { a INTEGER (0..value), b Type1 } END
註釋:
- AUTOMATIC TAGS是指缺省Tag,說明不關注模塊的Tag。
- IMPORTS聲明在其它模塊定義但在本模塊會用到的類型或者值。
- EXPORT聲明在本模塊之外可以訪問的類型或者值。
module後面加上了AUTOMATIC TAGS,這是什麼意思呢?在ASN.1中,tags是ASN.1消息中每個組件的內部標識符,以Address為例,我們希望給Address中的每個屬性都指定一個內部的標識符,如下所示:
Address::= SEQUENCE { street [0] VisibleString (SIZE (5 .. 50)) OPTIONAL, city [1] VisibleString (SIZE (2..30)), state [2] VisibleString (SIZE(2) ^ FROM ("A".."Z")), zipCode [3] NumericString (SIZE(5 | 9)) }
這裏面的[0] [1] 就是標識符,當然,我們可以在定義module的時候手動指定這些tags,但是如果我們使用AUTOMATIC TAGS,這些標識符會自動創建,從而避免了手動創建標識符可能帶來的問題。
對象標識符
編輯對象標識符(OBJECTIDENTIFIER,OID)類型,用層次的形式來表示標準規範。標識符樹通過一個點分的十進制符號來定義,這個符號以組織子部分然後是標準的類型和各自的子標識符開始。
BER基本編碼規則
編輯用ASN.1語言書寫的變量必須轉換為串行的字節流才能在網絡中傳輸。為此,ASN.1又提供了基本編碼規則(BER)來描述傳輸過程中內容的表示。BER的全稱是Basic Encoding Rules,它是最早的編碼規則,使用Tag-Length-Value(TLV)的格式對所有信息進行編碼。在BER中,每個數據元素都被編碼為類型標識符、長度描述、實際數據元素,以及可選的內容結束標記。
約定八位位組:八比特組成。八位位組的二進制位編號從8到1,第8位為最高有效位,第1位位最低有效位。
編碼結構分為3部分:
- 標籤(tag)字段:關於標籤類別和編碼格式、數據類型的編碼信息。
- 長度(Length)字段:定義內容字段的長度。
- 值(Value)字段:包含實際的數據 。
標籤tag字段
編輯其中7-8bits表示的是Tag class。
class | value | 描述 |
---|---|---|
Universal | 0 | ASN.1的native類型 |
Application | 1 | 該類型僅對一種特定應用程式有效 |
Context-specific | 2 | 這種類型依賴於context |
Private | 3 |
第6bit表示的是這個類型是簡單類型還是組合類型,簡單類型用0,組合類型用1。
第1-第5bits只用來表示0-30的值的範圍。如果想要表示超出30範圍的值,那麼可以使用兩個byte,前面一個byte的1-5bits全部用1表示,後面一個byte的第8bit用1表示,剩下的7個bits用來表示真實的值。
type名稱 | 基礎類型還是組合類型 | 編碼值(十進制) |
---|---|---|
End-of-Content (EOC) | 基礎類型 | 0 |
BOOLEAN | 基礎類型 | 1 |
INTEGER | 基礎類型 | 2 |
BIT STRING | 兩者皆可 | 3 |
OCTET STRING | 兩者皆可 | 4 |
NULL | 基礎類型 | 5 |
OBJECT IDENTIFIER | 基礎類型 | 6 |
Object Descriptor | 兩者皆可 | 7 |
EXTERNAL | 組合類型 | 8 |
REAL (float) | 基礎類型 | 9 |
ENUMERATED | 基礎類型 | 10 |
EMBEDDED PDV | 組合類型 | 11 |
UTF8String | 兩者皆可 | 12 |
RELATIVE-OID | 基礎類型 | 13 |
TIME | 基礎類型 | 14 |
Reserved | 示例 | 15 |
SEQUENCE and SEQUENCE OF | 組合類型 | 16 |
SET and SET OF | 組合類型 | 17 |
NumericString | 兩者皆可 | 18 |
PrintableString | 兩者皆可 | 19 |
T61String | 兩者皆可 | 20 |
VideotexString | 兩者皆可 | 21 |
IA5String | 兩者皆可 | 22 |
UTCTime | 兩者皆可 | 23 |
GeneralizedTime | 兩者皆可 | 24 |
GraphicString | 兩者皆可 | 25 |
VisibleString | 兩者皆可 | 26 |
GeneralString | 兩者皆可 | 27 |
UniversalString | 兩者皆可 | 28 |
CHARACTER STRING | 組合類型 | 29 |
BMPString | 組合類型 | 30 |
DATE | 基礎類型 | 31 |
TIME-OF-DAY | 基礎類型 | 32 |
DATE-TIME | 基礎類型 | 33 |
DURATION | 基礎類型 | 34 |
OID-IRI | 基礎類型 | 35 |
RELATIVE-OID-IRI | 基礎類型 | 36 |
長度字段
編輯長度字段:用來表示值字段的八位位組的數量。
- 確定格式(編碼時知道長度
- 長格式:第8比特為1,剩下7個bit表示1-126個後續byte的個數。
- 短格式:第8比特為0,剩下7個bit表示0-127
- 不確定格式:第8比特為0,剩下7個bit全為1
- 保留:第8比特為0,剩下7個bit全為0
規則如下
- 若編碼是簡單類型,則使用確定格式;
- 若編碼是構造的,並且編碼立即可用,既可以使用確定格式,也可以使用不確定格式,由發送者選擇;
- 若編碼是構造的,但編碼不是立即可用,則使用不確定格式。
值字段
編輯值字段:由零個或多個八位位組組成,並按不同類型數據值的不同規定對它們進行編碼
- End-of-Content (EOC),編碼為00,基礎類型
- 布爾值的編碼 由1個字節組成。FALSE為00; TRUE為FF。
- TRUE的編碼:01 01 FF
- FALSE的編碼:01 01 00
- 整數編碼 採用二進制補碼形式編碼。
- 0 編碼 02 01 00
- 127 編碼 02 01 7F
- 256 編碼 02 02 01 00
- -129 編碼 02 02 FF 7F
- 空值 標籤 UNIVERSAL 5, 編碼 05 00
- 位串值的編碼
- 簡單類型
- 構造類型
- 對象標識符的編碼,為簡單類型。
- 八位位組串和字符串類型值的編碼
- IA5String類型字符串「ACE」 編碼 16 03 41 43 45 H
- 八位位組串「ACE0」 編碼 04 02 AC E0 H
- 序列值的編碼,為構造類型。
- 序列類型{name IAString, ok BOOLEAN},值{name 「smith」, ok TRUE}的編碼:30 0A 16 05 73 6D 69 74 68 01 01 FF
- 集合值的編碼,有多種編碼。
參考
編輯- ↑ X.680 : Information technology - Abstract Syntax Notation One (ASN.1): Specification of basic notation.www.itu.int.於2021年4月29日查閱.