描述ASN.1编码规则的标准
ITU-T Rec. X.690 | ISO/IEC 8825-1 (BER, CER and DER)
ITU-T Rec. X.691 | ISO/IEC 8825-2 (PER)
ITU-T Rec. X.692 | ISO/IEC 8825-3 (ECN)
ITU-T Rec. X.693 | ISO/IEC 8825-4 (XER)
一.BER编码规则
描述了如何将ASN.1 类型的值编码成字节串的方法。BER的语法传输格式一直是TLV三元组<Type, Length,Value>
- tag(标志域): 指明数据类型,占用一个字节常见的类型有
#define BER_TYPE_BOOLEAN 0x01
#define BER_TYPE_INTEGER 0x02
#define BER_TYPE_BIT_STRING 0x03
#define BER_TYPE_OCTET_STRING 0x04
#define BER_TYPE_NULL 0x05
#define BER_TYPE_OID 0x06
#define BER_TYPE_SEQUENCE 0x30
#define BER_TYPE_COUNTER 0x41
#define BER_TYPE_GAUGE 0x42
#define BER_TYPE_TIME_TICKS 0x43
#define BER_TYPE_NO_SUCH_OBJECT 0x80
#define BER_TYPE_NO_SUCH_INSTANCE 0x81
#define BER_TYPE_END_OF_MIB_VIEW 0x82
#define BER_TYPE_SNMP_GET 0xA0
#define BER_TYPE_SNMP_GETNEXT 0xA1
#define BER_TYPE_SNMP_RESPONSE 0xA2
#define BER_TYPE_SNMP_SET 0xA3
#define BER_TYPE_SNMP_GETBULK 0xA5
#define BER_TYPE_SNMP_INFORM 0xA6
#define BER_TYPE_SNMP_TRAP 0xA7
#define BER_TYPE_SNMP_REPORT 0xA8
- 长度域(length):指明值域的长度,长度不等,一般为一到三个字节。其格式可分为短格式(后面的值域长度<=127),长格式.
(1)定长方式
length=30 表示为1E(16进制),30长度域为 0001 1110 没有超过127;
- 长格式 :表示方法为1(bit)K(7bit)K个八位长度(K Byte)
length = 169 转换为 81 A9(169长度超过127,长度域为1000 0001 1010 1001;169是后8位的值,前8位的第一个1表示这是一个长格式的表示方法,前8位的后7位表示后面有多少个字节表示针对的长度000 0001后面有一个字节表示真正的长度 1010 1001是表示长度为169)
length=1500=>82 05 DC(1000 0010 0000 0101 1101 1100,先看第一个字节,表示长格式,后面有2 个字节表示长度,这两个字节是0000 0101 1101 1100 表示1500)
(2).不定长方式
Length所在八位组固定编码为0x80,但在Value编码结束后以两个0x00结尾。这种方式使得可以在编码没有完全结束的情况下,可以先发送部分消息给对方。
Length所在八位组固定编码为0x80,但在Value编码结束后以两个0x00结尾。这种方式使得可以在编码没有完全结束的情况下,可以先发送部分消息给对方。
-
值域(value)
-
整型Integer的编码 integer::=0x02 length{byte} (表示重复),最高位代表符号位,去掉多余的0。对于正数,如果最高比特位为0则直接编码;如果为1,则在最高比特位之前增加一个全0的八位组。
-
最高位为0:
0BBBBBBB
-
最高位为1:
00000000|1BBBBBBB
-
- 例: 对于负数,先取绝对值进行编码,再取反,最后加1
1500=>02 02 05 DC
40000=>02 03 00 9C 40
-129=>129=>0000 0000 1000 0001->1111 1111 0111 1110 ->(加1)->FF 7F 最终为02 02 FF 7F
-
布尔值的编码由1个字节组成。FALSE为00; TRUE为FF。
- TRUE的编码: 01 01 FF
- FALSE 的编码: 01 01 00
-
字符串类型的编码 string::=0x04 length{byte}* 例如:04 06 70 75 62 6c 69 63表示字符串public
-
位串(BITSTRING)类型 :编码规则:位串的第一位放到第一个负载字节的第8位;位串的第二位放到第一个负载字节的第7位; 依此类推.填充满第一个负载字节,就继续填充第二个负载字节.如果最后一个负载字节未被填充满,空的位用0来填充, 0的个数存放到头部用来表示填充数据的那个字节里.
例如:
ASN定义如下:
A ::= BIT STRING {a(0),b(1),c(2),d(3),e(4),f(5),g(5),h(6),i(7),j(8),k(9),l(10)} (SIZE(16))
位串赋值为a,e,f,g,i,l
位串{1,0,0,0,1,1,1,0,1,0,0,1}
开始填充负载字节.第一个字节填充后为10001110= 0x8E; 第二个字节填充后为10010000 = 0x90, 低位4个0为填充的空位.则,负载为2个字节加上表示填充0个数的一个字节0x04总共3个字节.则完整的编码为:0x03 03 04 8E 90.
-
空类型的编码 null::=0x05 0x00
-
对象标识ObjectID(oid)编码 SNMP服务器维护的所有管理信息库(MIB)对象采用ObjectID表示,其编码规则如下:objectID::=0x06 length {subidentifier}*
(1) subidentifier::= {leadingbyte}* lastbyte
(2) leadingbyte::=1 7bitvalue
(3) lastbyte::=0 7bitvalue
(4) 首两个ID被合并为一个字节X*40+Y
虽然规则很多,但由于大多数子对象标识在0~127,只需按规则(1)、(4)即可;当子对象标识大于127,则按规则(2)、(3)、将其分解为多个字节,最后一个字节的高位为0,其余字节的高位为1
如:1.3.6.1.810.1,根据规则(5),首两个子对象标识1.3被合并为2B(1 *40 +3=40+3=43); 子对象标识810超过127,根据规则(2)、(3)将其拆分为两个字节86 2A (810=11 0010 1010==>1000 0110 0010 1010);
整个MIB被编码为:0x06 0x06 0x2b 0x06 0x01 0x86 0x2a 0x01。
如:1.2.840.113549 最终编码如下:06 06 2a 86 48 86 f7 0d
-
首两个ID被合并为一个字节X*40+Y
-
每个字首先被分割为最少数量的没有头零数字的7位数字.这些数字以big-endian格式进行组织,并且一个接一个地组合成字节.
举例: 30331 = 1* 128^2 + 108 * 128 + 123 分割成7位数字(0x80)后为{1,108,123}
- 除了编码的最后一个字节外,其他所有字节的最高位(位8)都为1.
设置最高位后变成{129,236,123}.如果该字只有一个7位数字,那么最高为0
MD5 OID的编码:
1. 将1.2.840.113549.2.5转换成字数组 {42, 840, 113549, 2, 5}.
2. 然后将每个字分割为带有最高位的7位数字,{
{0x2A},{0x86,0x48},{0x86,0xF7,0x0D},{0x02},{0x05}}
3. 最后完整的编码为 0x06 08 2A 86 48 86 F7 0D 02 05.
- sequence组合类型的编码 sequence::=0x30 length{asndata}*
如:30 05 02 01 10 05 00表示一个sequence结构,内含两个成员,其中一个为整型16,另一个为空类型(NULL)。
例:考虑如下序列
User ::== SEQUENCE{
ID INTEGER,
Active BOOLEAN
}
当取值为{32,TRUE}时,编码为 0x30 06 02 01 20 01 01 FF 在ASN.1文档里,使用空格来表示编码的属性.
0x30 06
02 01 20
01 01 FF
二.CER与DER
CER与DER(Canonical and Distinguished Encoding Rules)
1 更多限制规则的需求
在X.400 和X.500中应用接力传递消息,会使用到X.509数字签名(Digital Signature),其过程如下图所示:
Figure 3-25 接力传递消息
发送方发送v的编码结果c1(v),同时发送其数字签名σ(c1(v));中继收到消息后,解码得到v,保留签名,发送时重新编码发送结果为c2(v);接收方收到结果后,解码得到v,同时对c2(v)计算数字签名σ(c2(v)),通过比较σ(c1(v))与σ(c2(v))是否相同来确定消息内容是否被修改。
在上面的过程中,如果直接使用BER编码规则,比如存在BOOLEAN类型的值“TRUE”,则因为两次编码过程c1和c2可能对TRUE的编码结果不同,从而导致数字签名比较不通过。
通常,我们称不给因具体实现和编码过程动态因素留出自由发挥余地的编码规则为规范编码规则(Canonical)。从BER中派生出两种规范编码规则,分别为CER(Canonical Encoding Rules)和DER(Distinguished Encoding Rules)。这两种规则是BER规范的特例,因此BER解码器能解码这两种规则的传输语法,反之则不然。
这两套编码规则为抽象值和他们的编码提供了一一对应的关系。应用这个属性,接收应用层可以不用了解具体结构和类型,就能比较接收的八位组流。
这两套规则的主要区别在于:CER针对不定长格式,而DER针对定长格式。因此CER常应用在需要传输大量数据的