网络管理:基本编码规则(BER)


简单编码规则

基本编码规则(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

参考资料

《计算机网络管理(第三版)》雷震甲 编著,西安电子科技大学出版社

posted @ 2021-04-27 23:21  乌漆WhiteMoon  阅读(6243)  评论(0编辑  收藏  举报