在国际标准ITU-T X.690 《Information technology – ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER)》中定义了ASN.1编码规则。对于一般数据类型(比如Integer、octetstring、bitstring等),ASN.1编码的一般形式如下图所示:
对于Boolean类型,标志位取值为1,DER编码规则使用0xFF表示Ture,BER编码规则可使用任意非0值表示True,它们都使用0表示False,不管取值是True还是False,值的长度都是1个字节。于是True的DER编码如下图:
False的编码如下图:
ASN1采用一个个的数据块来描述整个数据结构,每个数据块都有四个部分组成:
1、数据块数据类型标识(一个字节)
数据类型包括简单类型和结构类型。
简单类型是不能再分解类型,如整型(INTERGER)、比特串(BIT STRING)、字节串(OCTET STRING)、对象标示符(OBJECT IDENTIFIER)、日期型(UTCTime)等。
结构类型是由简单类型和结构类型组合而成的,如顺序类型(SEQUENCE, SEQUENCE OF)、选择类型(CHOICE)、集合类型(SET)等。
l 顺序类型的数据块值由按给定顺序成员成员数据块值按照顺序组成,;
l 选择类型的数据块值由多个成员数据数据块类型中选择一个的数据块值;
l 集合数据块类型由成员数据块类型的一个或多个值构成。
这个标识字节的结构如下:
1.1. Bit8-bit7
用来标示 TAG 类型,共有四种,分别是universal(00)、application(01)、context-specific(10)和private(11)。
这两位为universal(00)时,bit5-bit1的值表示不同的universal的值:
标记(TAG) 对应类型
[UNIVERSAL 1] BOOLEAN [有两个值:false或true]
[UNIVERSAL 2] INTEGER [整型值]
[UNIVERSAL 3] BIT STRING [0位或多位]
[UNIVERSAL 4] OCTET STRING [0字节或多字节]
[UNIVERSAL 5] NULL
[UNIVERSAL 6] OBJECT IDENTIFIER [相应于一个对象的独特标识数字]
[UNIVERSAL 7] OBJECT DESCRIPTOR [一个对象的简称]
[UNIVERSAL 8] EXTERNAL, INSTANCE OF [ASN.1没有定义的数据类型]
[UNIVERSAL 9] REAL [实数值]
[UNIVERSAL 10] ENUMERATED [数值列表,这些数据每个都有独特的标识符,作为ASN.1定义数据类型的一部分]
[UNIVERSAL 12] UTF8String
[UNIVERSAL 13] RELATIVE-OID
[UNIVERSAL 16] SEQUENCE, SEQUENCE OF [有序数列,SEQUENCE里面的每个数值都可以是不同类型的,而SEQUENCE OF里是0个或多个类型相同的数据]
[UNIVERSAL 17] SET, SET OF [无序数列,SET里面的每个数值都可以是不同类型的,而SET OF里是0个或多个类型相同的数据]
[UNIVERSAL 18] NumericString [0-9以及空格]
[UNIVERSAL 19] PrintableString [A-Z、a-z、0-9、空格以及符号'()+,-./:=?]
[UNIVERSAL 20] TeletexString, T61String
[UNIVERSAL 21] VideotexString
[UNIVERSAL 22] IA5String
[UNIVERSAL 23] UTCTime [统一全球时间格式] (jaydon add ,比如 0x17)
[UNIVERSAL 24] GeneralizedTime
[UNIVERSAL 25] GraphicString
[UNIVERSAL 26] VisibleString, ISO646String
[UNIVERSAL 27] GeneralString
[UNIVERSAL 28] UniversalString
[UNIVERSAL 29] CHARACTER STRING
[UNIVERSAL 30] BMPString
[UNIVERSAL 31]... reserved for future use
1.2. bit6
表示是否为结构类型(1位结构类型);0则表明编码类型是简单类型。
bit6为 0 不再解析
1.3. bit5-bit1
是类型的TAG值。根据bit8-bit7的不同值有不同的含义,具体含义见上面的描述。
如 SEQUENCE 类型数据块,其TAG类型位UNIVERSAL(00),属于结构类型(1),TAG值为16(10000)所以其类型标示字段值为(00110000),即为0x30。
再如,证书扩展字段类型的数据块,TAG类型为(10),属结构类型(1),TAG的值为3(00011),所以其类型标示字段值为(10100011),即为0xA3
context-specific
这两位为context-specific(10)时,bit5-bit1的值表示特殊内容:
[0] –- 表示证书的版本 (add: A0 )
[1] –- issuerUniqueID,表示证书发行者的唯一id
[2] –- subjectUniqueID,表示证书主体的唯一id
[3] –- 表示证书的扩展字段 (add: A3 )
示例
0x30
二进制 : 0011 0000
Bit8 Bit7 是universal(00)
Bit6 是1 为结构类型(1位结构类型)
Bit5-Bit1的值表示不同的universal的值: 0x1 0000 = 16 ,解析如下:
[UNIVERSAL 16] SEQUENCE, SEQUENCE OF [有序数列,SEQUENCE里面的每个数值都可以是不同类型的,而SEQUENCE OF里是0个或多个类型相同的数据]
0x02
二进制 : 0000 0010
Bit8 Bit7 是universal(00)
Bit6 是0 为简单类型
Bit5-Bit1的值表示不同的universal的值: 0x0 0010 = 2 ,解析如下:
[UNIVERSAL 2] INTEGER [整型值]
0x31
二进制 : 0011 0001
Bit8 Bit7 是universal(00)
Bit6 是1 为结构类型(1位结构类型)
Bit5-Bit1的值表示不同的universal的值: 0x1 0001 = 17 ,解析如下:
[UNIVERSAL 17] SET, SET OF [无序数列,SET里面的每个数值都可以是不同类型的,而SET OF里是0个或多个类型相同的数据]
0x06
二进制 : 0000 0110
Bit8 Bit7 是universal(00)
Bit6 是0为简单类型
Bit5-Bit1的值表示不同的universal的值: 0x0 0110 = 6 ,解析如下:
[UNIVERSAL 6] OBJECT IDENTIFIER [相应于一个对象的独特标识数字]
0x13
二进制 : 0001 0011
Bit8 Bit7 是universal(00)
Bit6 是0为简单类型
Bit5-Bit1的值表示不同的universal的值: 0x1 0011 =19 ,解析如下:
[UNIVERSAL 19] PrintableString [A-Z、a-z、0-9、空格以及符号'()+,-./:=?]
0x0C
二进制 : 0000 1100
Bit8 Bit7 是universal(00)
Bit6 是0为简单类型
Bit5-Bit1的值表示不同的universal的值: 0x0 1100 =12,解析如下:
[UNIVERSAL 12] UTF8String
0x03
二进制 : 0000 0011
Bit8 Bit7 是universal(00)
Bit6 是0 为简单类型
Bit5-Bit1的值表示不同的universal的值: 0x0 0011 = 3 ,解析如下:
[UNIVERSAL 3] BIT STRING [0位或多位]
0xA0
二进制 : 1010 0000
Bit8 Bit7 是context-specific(10)
Bit6 是1 为结构类型(1位结构类型)
Bit5-Bit1 0 0000 解析如下:
Bit8 Bit7 是context-specific(10)时,bit5-bit1的值表示特殊内容
x509和csr中对于version的比较
x509中:
x509中 version是 包裹在Context[0]中的
csr中:
csr中version没有被context包裹
x509和csr中context的比较
x509中 A0是 version , A1 是 issuerUniqueID , A2是 subjectUniqueID, A3是extensions
csr中:A0是 attributes (可选的)
bistring类型的编码
以ECC证书中的签名值 和公钥为例:(前面都会多一个00)
bistring类型的编码方法:bistring类型的标志位取值为3。不包含任何比特的比特串被称为“空比特串”(empty bitstring)。其他比特串,例如对于“10101”这个比特串,其长度(即比特个数)为5,在这里将其表示为:{1,0,1,0,1}。考虑到比特串的长度不一定刚好是8的整数倍,而计算机中的最小存储单位是“字节”,一个字节包含8个比特,为了便于在计算机中表示比特串,对bitstring类型做ASN.1编码时,要做一些补位等额外的操作,按照以下步骤进行:
1) 补位;当比特串的长度不是8的整数倍时,要先对比特串进行补位。方法是在比特串的末尾添加比特 0,直到整个比特串的长度刚好是8的整数倍时停止。
2) 添加补位长度字节;将补位时添加的比特个数用一个字节表示,添加到补位结果比特串的前面。如果比特串的长度恰好是8的整数倍,此时未补位,那么此时必须在原始比特串前面添加一个0x0字节,以表示添加的补位比特个数为0。由此可知,补位长度这一个字节的取值范围为0到7。在进行过补位情况下(即原始比特串长度不是8的整数倍),补位长度字节和补位结果比特串共同组成了ASN.1 bitstring编码的负载部分;在未补位情况下(即原始比特串长度是8的整数倍),补位长度字节0和原始比特串共同组成了ASN.1 bitstring编码的负载部分。
3)编码。按照标志位、负载长度、负载的次序,进行编码。
对于比特串{1,0,1,0,1},编码过程如下图:
对于空串(empty bitstring),其编码为:0x3 0x0
注意空串编码中仅包含标志位和负载长度,不包含负载部分。
如果一个比特串中不包含比特1,例如 {0},该比特串仅包含一个比特0,其DER编码为:0x3 0x1 0x0
(实际上一个完全由比特0组成的比特串并无实际意义,一般用一个比特 {0} 来统一表示这一类的比特串)
DER编码规则要求输入编码器的原始比特串的最后一个比特必须是1,即类似 {1, 0, 1, 0, 0} 这种以比特0作为结尾比特的比特串不是符合要求的编码器输入。而BER编码规则不要求输入编码器的原始比特串的最后一个比特必须为1,在编码前,甚至可以在一个比特串的末尾再添加任意个比特0。例如:在应用BER编码规则时,{1. 0, 1} 可以编码为以下不同的形式:
0x3 0x2 0x5 0xA0
0x3 0x3 0x5 0xA0 0x0
0x3 0x4 0x5 0xA0 0x0 0x0
0x3 0x5 0x5 0xA0 0x0 0x0 0x0
.......
使用BER编码规则时,对同一个对象编码,其编码结果可以是不唯一的。而使用DER编码规则时,对同一对象编码,其编码结果一定是唯一的。在实际应用中,大多数情况下都使用DER编码。
到这里也就可以理解,签名结果(或者公钥)的比特串(不是字节串)肯定是8的倍数,因此不需要补位,即补位长度字节使0x00, 以表示添加的补位比特个数为0