目录简单编码规则简单编码例题部分常用标签例题一例题二例题三例题四例题五例题六例题七例题八字段扩充对标签值扩充扩充情况扩充方法扩充样例对 Length 字段扩充扩充情况扩充方法扩充样例参考资料
简单编码规则
基本编码规则(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
参考资料
《计算机网络管理(第三版)》雷震甲 编著,西安电子科技大学出版社
最新评论