zoukankan      html  css  js  c++  java
  • 网络管理:基本编码规则(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
    

    参考资料

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

  • 相关阅读:
    ThinkPHP 3.2.2 视图模板中使用字符串截取函数
    Java实现洛谷 P2802 回家
    Java实现洛谷 P2802 回家
    Java实现 蓝桥杯VIP 算法提高 change
    Java实现 蓝桥杯VIP 算法提高 change
    Java实现 蓝桥杯VIP 算法提高 change
    Java实现蓝桥杯G将军
    Java实现蓝桥杯G将军
    Java实现蓝桥杯G将军
    Java实现 蓝桥杯 算法提高 字符串压缩
  • 原文地址:https://www.cnblogs.com/linfangnan/p/14711368.html
Copyright © 2011-2022 走看看