原创文章,转载请注明出处 http://boytnt.blog.51cto.com/966121/1351089。


上回说到打算深入研究一下ASN.1,先简单普及一下ASN.1编码的知识,想具体了解的请自行百度。


一个ASN.1结构由<TAG, LENGTH, VALUE>三部分组成,其中的Value可以也是一个<TAG, LENGTH, VALUE>结构,形成嵌套结构 <TAG, LENGTH, <TAG, LENGTH, VALUE>>。


TAG占1个字节,由三部分组成:第6-7bit表示类别,第5bit表示VALUE部分是否为另一个结构,第0-4bit表示原始类型。

7 6 5 4 3 2 1 0

--- - ---------

│ │ └──── 原始类型

│ └─────── 结构化位

└───────── 类别


LENGTH表示VALUE的长度,占1字节,如果为0x80,表示VALUE是不定长数据,直到连续的2个0x00才认为结构。如果不为0x80,先看最高位,为0表示短形式,低7位表示VALUE长度,如果为1表示长形式,低7位表示后面多少个字节是真正的数据。注意如果超过1字节,它是使用大字节序存储的。


JavaDoc里已经描述了SubjectPublicKeyInfo的结构了,只不过描述方式我们不太习惯,重新整理一下如下:

SEQUENCE {
    SEQUENCE {          //algorithm,我们不用关心具体结构
    }
    BIT STRING {        //SubjectPublicKey,以BIT STRING存储
        SEQUENCE {
            INTEGER     //modulus
            INTEGER     //publicExponent
        }
    }
}


OK,我们对照着ASN.1规范,试着把那个3082开头的大字符串解析一下,以下部分可能比较枯燥。

  二进制          解析
--------------------------------------------------------------
30  0011 0000       TAG:类型00=通用,1=结构体,10000=16=SEQUENCE
82  1000 0010       LEN:定长,长形式,后面2字节是长度
01                     长度 0x122=290字节,注意是大字节序
22
30  0011 0000       TAG:类型00=通用,1=结构体,10000=16=SEQUENCE
0D  0000 1101       LEN:定长,短形式,13字节
06                  VAL:13字节,我们不关心内容,跳过
09
.
.
.
05
00
03  0000 0011       TAG:类型00=通用类型,0=简单数据,00011=3=BIT STRING
82  1000 0010       LEN:定长,长形式,后面2字节是长度,注意是大字节序
01                     长度 0x10f=271字节
0F
00                  保留字
30  0011 0000       TAG:类型00=通用类型,1=结构体,10000=16=SEQUENCE
82  1000 0010       LEN:定长,长形式,后面2字节是长度,注意是大字节序
01                     长度 0x10a=266字节
0A
02  0000 0010       TAG:类型00,0=简单数据,00010=2=INTEGER
82  1000 0010       LEN:定长,长形式,后面2字节是长度,注意是大字节序
01                      长度=0x101,257字节
01
00                  VAL:257字节,是公钥中的modulus
8C
.
.
.
F9
0D
02  0000 0010       TAG:类型00,0=简单数据,00010=2=INTEGER
03  0000 0011       LEN:定长,短形式,3字节
01 00 01            VAL:3字节,是公钥中的publicExponent


OK,再整理一下,变成大家喜闻乐见的形式。

类型  长度位  实际长度
-----------------------------------------------
30    82     01 22     SEQUENCE {
30    0D     0D            SEQUENCE {
                           }
03    82     01 0F         BIT STRING {
30    82     01 0A             SEQUENCE {
02    82     01 01                 INTEGER
                                       00 8C 21 47 51 E6 EA 33 37 80 80 F6 4B F5 5C 08
                                       88 D3 EF A4 DF 08 79 43 18 06 9D DF D1 4A 3A B6
                                       .......
                                       35 C8 BC CF CB 08 A6 71 98 3A 27 E8 B0 3F 5B F9
                                       0D
02    03     03                    INTEGER
                                       01 00 01
                               }
                           }
                       }


我们终于得到modulus和publicExponent了,上面那两个INTEGER就是。如果你觉得不放心,在用Java生成publicKey的时候,把modulus和publicExponent也顺便输出一下用于检验,代码如下:

/*********** Java代码 ***********/
System.out.println(bytes2hex(publicKey.getModulus().toByteArray()));
System.out.println(bytes2hex(publicKey.getPublicExponent().toByteArray()));


是否觉得胜利在望了?


未完待续……