由于工作需要必须解析ASN.1文件BER编码,资料如下:
一个标准的ASN.1编码对象有四个域:对象标识域、数据长度域、数据域以及结束标志(可选,在长度不可知情况下需要,openssl中没有该标志)。
    【对象标识域】
    对象标识域有两种形式,低Tag数字(Tag值在0到30)和高Tag数字(Tag值大于30)形式。
    低Tag数字形式只有一个字节,包含三部分,从低位为1开始编号,8和7位是Tag类型,共有四种,分别是universal(0 0)、application(0 1)、context-specific(1 0)和private(1 1);第6位是0,表明编码类型是基本类型,第5-1位是Tag值。 
    高Tag数字形式可以有两个或多个字节,第一个字节跟低Tag数字形式一样,但低5位值全为1,而在后续的第二个和其后的字节中给出Tag值,这些字节都只使用了低7位为数据位,最高位都设为0,但最后一个字节的最高位设为1,采用高位优先,经可能少的数字原则。
    【数据长度域】
    数据长度域也有两种形式,短形式和长形式。
    短形式的数据长度域只有一个字节,第8位为0,其它低7位给出数据长度。
    长形式的数据长度域有2到127个字节。第一个字节的第8位为1,其它低7位给出后面该域使用的字节的数量,从该域第二个字节开始给出数据的长度,基于256,高位优先。
    【数据域】
    数据域给出了具体的数据值。该域的编码对不同的数据类型不一样,这里就不在一一详述了,有兴趣的可以参看参考资料。
    【一个编码例子】
    下面是SSLDocument给出的对一个对象进行DER编码的例子,更多的例子可以参看本文给出的参考资料。
    例子使用的对象是ASN.1定义的BIT STRING类型的对象,其编码的步骤如下:
    1.对位串使用"0"进行填补,使其长度为8的整数倍(如果已经是整数倍,则不需要进行填补);
    2.计算填补的位数并写下来,成为数据内容的第一个字节;
    3.写入填补后的位串,高位字节优先。这些数据跟前面的一个字节组成数据内容的全部字节;
    4.在这些数据前面加上一个头字节,这个字节定义如下(编号是从低位为1开始):
     第8、7位:00(universal类型)
     第 6 位 :0(表明是基本类型,有限长度的编码)
     第5-1位:0x03(表明是BIT STRING)
    这个字节定义了对象标识域;
    5.然后在对象标识域字节和数据字节之间加入下面计算的定义的字节:
     计算有多少字节的数据内容(对象标识域数据除外),如果少于127字节,那么就定义一个字节如下:
     第8位:0
     第7-1位:数据内容的字节数量
     如果数据内容的字节数量大于127,就需要定义两个或多个字节,其中,第一个字节的定义如下:
     第8位:1
     第7-1位:该域后面还有多少字节
     其后的字节是数据内容的字节数量,每字节基于256,高位优先
    下面是一个实际的数据例子:
    位串:'01000100111011'
    1.补齐两个0在后面,成为8的整数倍,得到'0100010011101100';
    2.'02'作为第一个数据内容的字节;
    3.'44 ec'作为其余的数据内容的字节;
    4.'03'作为前面的对象标识字节;
    5.因为BIT STRING的tag值3<=127,所以只有一个字节的长度域'03' 
 那么得到的这个位串的DER编码就是03 03 02 44 ec,其中,第一个字节是对象标识域,第二个字节是数据长度域,其他为数据域。 基本的思路就是定义一些TYPE,根据Tag来判断后面的内容是那种类型,然后解析
现求简单的源代码,谢谢,回帖者有分

解决方案 »

  1.   

    ASN.1的基本编码规则定义了一种或多种把任意ASN.1值表示成octet string的方法,缩写为BER。(当然还有其它的方法,但是BER是OSI中转换这些值的标准)
        使用BER,一个ASN.1的值有三种编码方法,选择哪种取决于值的类型和值的长度是否已知。这三种方法是:基本的,定长编码;结构化的,定长编码;及,结构化的,不定长编码。简单的non-string类型使用第一种(简单、定长编码);结构类型可使用任一种结构化的编码方法;简单的string类型根据值的长度是否已知可使用任一种方法。隐式标签定义的类型可使用下层类型的方法,显式标签定义的类型使用结构化的编码方法。
        每种BER编码方法都有三或四部分:    ●Identifier octets:定义了ASN.1值的类和标签值,指明编码方法是简单化的还是结构化的。
        ●Length octets:对于定长编码方法,它指出了内容octet的个数;对于结构化、非定长编码方法,它指名长度是不确定的。
        ●Contents octets:对于简单的、定长编码方法,它给出了值的具体表示;对于结构化的方法,它给出了值的内容的BER编码的串联。
        ●End-of-contents octets:对于结构化、非定长的编码方法,它表示内容结束;对于其它方法,没有该部分。
        在下面的章节中介绍了这三种编码方法。
    3.1、简单定长方法(Primitive, definite-length method)    这种方法用于简单类型及通过对简单类型使用隐式标签生成的类型。它要求值的长度是事先预知的。BER编码的部分定义如下:
    1.Identifier octets,有两种形式:较小的标签值(标签值在0和30之间)和较大的标签值(标签值大于等于31)    ●Low-tag-number form:一个octet。Bit8和bit7表示类(如表2),bit6值为0,表示编码方法为简单化的。Bit5-1给出了标签值。如下表所示:
                  Class        Bit 8    Bit 7
                  universal        0    0 
                  application        0    1
                  context-specific    1    0
                  private        1    1
        ●High-tag-number form:两个或多个octet。第一个octet形式如low-tag-number form,但是bit5-1均为1。第二个和以后的octet给出标签值,基于128,最高位在先,以便使用尽可能少的数字,每个octet的bit8都置为1,最后一个为0。2.Length octets:有两种格式:短型(长度在0至127之间)和长型(长度在0至21008-1之间)    ●Short form: 一个octet,bit8为0,bit7-1表示长度。
        ●Long form: 2-127个octet。第一个octet的Bit8为1,bit7-1表示后面有多少个用于表示实际长度的octet。第二个和随后的octet给出实际长度,基于256,高位数字在先。3.Contents octets:给出了值的具体表示(如果类型是由隐式标签定义的,则给出了下层类型的值)特定类型的细节详见第5节。
    3.2 结构化定长方法(Constructed, definite-length method)     结构化的、定长方法适用于简单的string类型、结构类型、在二者基础上通过隐式标签生成的类型和在任何类型基础上由显式标签生成的类型。要求值的长度事先已知。BER编码方法各部分如下:     1.Identifier octets:与第3.1节介绍的一样,但bit6的值为1,表示编码方法是结构化的。
         2.Length octets:见第3.1节。
         3.Contents octets,值的组件的BER编码的串联
        ●对于简单string类型和在其基础上由隐式标签生成的类型,是值的连续子串的BER编码的串联(隐式标签的下层值)
        ●对于结构类型和在其基础上由隐式标签生成的类型,是值的组件的BER编码的串联(隐式标签的下层值)
        ●对于在任何类型基础上使用显式标签生成的类型,是下层值的BER编码特定类型的细节见第5节。3.3 结构化非定长方法(Constructed, indefinite-length method)    结构化的、非定长编码用于简单string类型、结构类型、在二者基础上使用隐式标签生成的类型和在任何类型基础上使用显式标签生成的类型。不要求事先知道值的长度。BER编码各部分如下:    ●Identifier octets,见第3.2节
        ●Length octets.一个octet,值为80
        ●Contents octets.见第3.2节。
        ●End-of-contents octets两个octet,为00  00。    由于end-of-contents octet出现在通常普通BER编码出现的位置(例如,在一个sequence值的内容octet出现的位置),可把00和00分别视为identifier和length octet。因此end-of-contents octet实际上是一个具有universal class,标签值为0,长度为0的值的简单定长编码。