
簡單編碼規則
基本編碼規則(Basic Encoding Rule)把 ASN.1 表示的抽象類型值編碼為字節串,這種字節串的結構為類型—長度—值,簡稱 TLV(Type-Length-Value)。
其中 Type 和 Length 都是1個字節,而且值部分還可以遞歸地再編碼為 TLV 結構,這樣就具有了表達復雜結構的能力。
編碼的第一個字節表示 ASN.1 類型或用戶定義的類型,前2位用於區分 4 種標簽,第 3 位用於區分簡單類型和構造類型,其余 5 位表示標簽的值。
結合上述的說明,總結出 Type 字段的編碼格式如下:
留個懸念:5 位 2 進制的表示范圍是 0~31,為什么對標簽號的擴充以 30 為界限?
簡單編碼例題
部分常用標簽
例題一
布爾類型 FALSE、TRUE 的編碼,都用一個字節表示,FALSE 是 00,TRUE 是 FF。Bool 類型是通用標簽 UNIVERSAL,屬於簡單類型,標簽號為 1 號。根據上述的表格就可以寫出 Type 字段的二進制表示為 00000001,十六進制表示為 01。由於 FALSE、TRUE 都用一個字節表示,因此 L 字段值為 00000001,十六進制表示為 01。
Type | Length | Value |
---|---|---|
00 0 00001 | 00000001 | 00000000 |
01 | 01 | 00 |
Type | Length | Value |
---|---|---|
00 0 00001 | 00000001 | 11111111 |
01 | 01 | FF |
例題二
十進制數 256 的編碼,把這個數用二進制表示就是 00000001 00000000,十六進制為 01 00 需要 2 字節。int 類型是通用標簽 UNIVERSAL,屬於簡單類型,標簽號為 2 號,根據上述的表格就可以寫出 Type 字段:00000010。由於這個數用二進制表示需要 2 字節,所以 L 字段值為 00000010,十六進制表示為 02。
Type | Length | Value |
---|---|---|
00 0 00010 | 00000010 | 00000001 00000000 |
02 | 02 | 01 00 |
例題三
比特串 10101 的編碼,由於傳輸時以字節為最小單位,不足部分補 0,因此需要有額外的字節來表示有多少比特是補足的。比特串第三個字節 03 表示值部分的最后 3 個比特未用,第四個字節是值部分,A8H 即 10101000。由於需要 2 個字節表示,所以 L 字段值為 02。
bit str 類型是通用標簽 UNIVERSAL,屬於簡單類型,標簽號為 3 號,根據上述的表格就可以寫出 Type 字段:00000011。
Type | Length | Value |
---|---|---|
00 0 00011 | 00000010 | 00000011 10101000 |
03 | 02 | 01 A8 |
例題四
字節串 ACE 的編碼,由於字節串總是占用整數個字節,因而不必說明未占用的比特數。沒有說明值的位都認為是 0,故最后一個字節寫為 E0,可見字節串類型也遵循靠左存放的原則。
octet str 類型是通用標簽 UNIVERSAL,屬於簡單類型,標簽號為 4 號,根據上述的表格就可以寫出 Type 字段:00000100。
Type | Length | Value |
---|---|---|
00 0 00100 | 00000010 | 10101100 11100000 |
04 | 02 | AC E0 |
例題五
NULL 的編碼,NULL 類型只有一個值 NULL,其標簽是 UNIVERSAL 5。由於這個類型是空類型,無需存儲或傳送它的值,第二個字節 00 表示值長度為 0。
Type | Length | Value |
---|---|---|
00 0 00101 | 00000000 | |
05 | 00 |
例題六
序列類型 SEQUENCE{madeofwood BOOLEAN, length INTEGER} 的值 {madeofwood TRUE,length 62}的編碼。SEQUENCE 類型是通用標簽 UNIVERSAL,屬於構造類型,標簽號為 16 號,根據上述的表格就可以寫出 Type 字段:00110000。
此處用到的是 TLV 結構的嵌套方式,表示出了 SEQUENCE 類型的編碼。
例題七
集合類型 SET{breadth INTEGER, bent BOOLEAN} 的值 {breadth 7, bent FALSE} 的編碼。SET 類型是通用標簽 UNIVERSAL,屬於構造類型,標簽號為 17 號,根據上述的表格就可以寫出 Type 字段:00110001。由於集合類型的元素是無序的,所以有 2 種編碼的方式。
例題八
在安全協議設計中定義了一個口令字類型,並賦予應用標簽 27:Password::=[APPLICATION 27] OCTET STRING。Password 是 APPLICATION 類型標簽,是構造類型,標簽號為 27 號,根據上述的表格就可以寫出 Type 字段:01111011。
對於這個類型的一個值 “Sesame”,可得到如下編碼:
字段擴充
對標簽值擴充
擴充情況
例如寫出標簽[APPLICATION 35]的二進制表示,寫出來是 01110001 1 需要 9 位二進制才能編碼,但是 Type 是 1 個字節顯然不夠,這時就需要對標簽值進行擴充。
擴充方法
當標簽值大於 30 時,需要進行擴充。方法是當標簽值大於等於 31 時這 5 位置全 1 作為轉義符,實際的標簽值編碼表示在后續字節中。
后續字節的左邊第一位表示是否為最后一個擴充字節,只有最后一個擴充字節的左邊第一位置 0,其余擴充字節的左邊第一位置 1。這樣每個擴充字節只用了 7 位表示標簽值的編碼。
擴充樣例
例如標簽值 101 10010101 111001,由於表示標簽號的二進制位數超過 5 位需要字段擴充。因此將標簽值按照 7 位一組分開,其中最后一個字節的第一位置為 0,其他 2 個字節的第一位置為 1,用 0 填充空位后可編碼為:
×××11111 10000101 11001010 01111001
對 Length 字段擴充
擴充情況
Length 字段用於表示 Values 字段有多少字節,Length 為 1 個字節最多表示 Values 最多有 2^8 個字節。 當值部分長度超級長,超過了 2^8 個字符,Length 字段(8 位二進制)還能夠表示出 Value的長度嗎?顯然不行,所以需要進行擴充。
擴充方法
對長度字節的擴充方法是當小於 127 的數用長度字節的右邊 7 位表示,最左邊的一位置 0。
大於等於 127 的數用后續若干字節表示,原來的長度字節第一位置 1,其余 7 位指明后續用於表示長度的字節數。值得注意的是長度字節可表示的最大值為 126 而不是 127,這個值是為以后擴充保留的。
擴充樣例
例如 L 字段的值為 321 時,由於 321 的二進制表示為 00000001 01000001 需要 2 字節,需要進行擴充。原來的長度字節第一位置 1,其余 7 位指明后續用於表示長度的字節數,此處擴充 2 個字節因此為 10000010,擴充后表示為:
10000010 00000001 01000001
參考資料
《計算機網絡管理(第三版)》雷震甲 編著,西安電子科技大學出版社