ASN.1学习
ASN.1 抽象语法标记(Abstract Syntax Notation One),ASN.1是一种 ISO/ITU-T 标准(国际标准化组织 ISO,通信方面的建议 ITU-T 是由国际电信联盟 ITU 负责制定的),ASN.1是 定义抽象数据类型规格形式的标准。是用于 描述数据的表示、编码、传输、解码的灵活的记法。它 提供了一套正式、无歧义和精确的规则,以描述独立于特定计算机硬件的对象结构。
ISO要求所有的应用层和表示层数据交换都要用ASN.1抽象语法描述。
- ASN.1发送任何形式(音频、视频、数据等等)的信息都必须用数字传送。
- ASN.1只能包含信息的结构方面(没有已经定义的或考虑到的处理数据值的操作)。
- ASN.1它不是一个编程语言。
- ASN.1 本身只定义了表示信息的抽象句法,但是没有限定其编码的方法。
1. 编码规则
ASN.1 本身只定义了表示信息的抽象句法,但是没有限定其编码的方法。各种ASN.1 编码规则提供了由ASN.1描述其抽象句法的数据的值的传送语法(具体表达)。
- 基本编码规则(BER,Basic Encoding Rules)
- 规范编码规则(CER,Canonical Encoding Rules)
- 唯一编码规则(DER,Distinguished Encoding Rules)
- 压缩编码规则(PER,Packed Encoding Rules)
- XML编码规则(XER,XML Encoding Rules)
这些编码规则描述了如何将定义在ASN.1中的值译成适合传输的电码(例如:他们可以被转化为可传输的字节,或反向转化),其与机器、编程语言或者在应用程序中的表示无关。
简洁的二进制编码规则(BER、CER、DER、PER,但不包括 XER)可当作更现代 XML 的替代。然而,ASN.1 支持对数据的语义进行描述,所以它是比 XML 更为高级的语言。
ASN.1 的描述可以容易地映被射成 C 或 C++ 或 Java 的数据结构,并可以被应用程序代码使用,并得到运行时程序库的支持,进而能够对编码和解码 XML 或 TLV 格式的,或一种非常紧凑的压缩编码格式的描述。
2. 数据类型
- 简单类型 (Simple types):没有任何组件,用于编码基本的数据类型。 如整型,字符串,二进制数据等。
- 结构类型 (Structured types):具有组件,用于编码复杂数据类型。如 X509 证书中的公钥。
- 标记类型 (Tagged types):用于编码从其他几种类型引申而来的类型。
- 其他类型 (Other types):CHOICE 或 Any。
基本类型 | 含义 |
---|---|
NULL | 只包含一个值NULL,用于传送一个报告或者作为CHOICE类型中某些值 |
INTEGER | 全部整数(包括正数和负数) |
REAL | 实数,表示浮点数 |
ENUMERATED | 标识符的枚举(实例状态机的状态) |
BIT STRING | 比特串 |
OCTET STRING | 字节串 |
OBJECT IDENTIFIER, RELATIVE-OID | 一个实体的标识符,它在一个全世界范围树状结构中注册 |
EXTERNAL, EMBEDDED PDV | 表示层上下文交换类型 |
…String(除了BIT STRING、OCTET STRING外) | 各种字符串,有NumericString、PrintableString、VisibleStirng、ISO64String、IA5String、TeletexStirng、T61String、VideotexString、GraphicString、GeneralString、UniversalString、BMPString和UTF8String |
CHARACTER STRING | 允许为字符串协商一个明确的字符表 |
UTCTime,GeneralizedTime | 日期 |
组合类型 | 含义 |
---|---|
CHOICE | 在类型中选择(相当于C中的联合) |
SEQUENCE | 由不同类型的值组成一个有序的结构(相当于C中的结构体) |
SET | 由不同类型的值组成一个无序的结构 |
SEQUENCE OF | 由相同类型的值组成一个有序的结构(相当于C中的数组) |
SET OF | 由相同类型的值组成一个无序的结构 |
String类型 | UNIVERSAL Tag | 字符表 | ESC | Multi |
---|---|---|---|---|
NumericString | 18 | 字符“0”到“9”,空格 | 是 | |
PrintableString | 19 | 字符“A” 到 “Z”,“a”到“z”,“0”到“9”,空格,单引号(’),圆括号(( ,)),加号(+),逗号(,),减号(-),点(.),斜杠(/),冒号(:),等号(=),问号(?) | 是 | |
VisibleString ISO646String | 26 | [ISOReg] entry no. 6; space | 是 | |
IA5String | 22 | [ISOReg] entry no. 1 & 6; space, delete | 是 | |
TeletexString T61String | 20 | [ISOReg] entry no. 6, 87, 102, 103, 106, 107, 126, 144, 150, 153, 156, 164, 165, 168; space, delete | 是 | |
VideotexString | 21 | [ISOReg] entry no. 1, 13, 72, 73, 87, 89, 102, 108, 126, 128, 129, 144, 150, 153, 164, 165, 168; space, delete | 是 | |
GraphicString | 25 | all the graphical sets (called G ) of [ISOReg]; space | 是 | |
GeneralString | 27 | all the graphical sets (called G ) and all the control characters (called C ) of [ISOReg]; space, delete | 是 | |
UniversalString | 28 | [ISO10646-1] | 是 | |
BMPString | 30 | the basic multilingual plane [ISO10646-1] (65,536 cells) | 是 | |
UTF8String | 12 | [ISO10646-1] |
3. 基本用法
3.1 基本规则
- 符号的定义没有先后次序:只要能够找到该符号的定义即可,而不必关心在使用它之前是否被定义过。
- 所有的标识符、参考、关键字都要以一个字母开头,后接字母(大、小写都可以)、数字或者连字符“-”(但不能以连字符“-”结尾,也不能连续出现两个连字符),不能出现下划线“_” 。
- 关键字一般都是全部大写的,除了一些字符串类型,如PrintableString,UTF8String等,因为这些都是由原类型OCTET STRING衍生出来的。
- 在标识符中,只有类型和模块名字是以大写字母开头的,其它标识符都是以小写字母开头的。
- 字符串有三种形式:
- 用引号引用的字符串: “This is a string”
- 单引号引用的二进制串后加大写字母B: ‘01101’B
- 单引号引用的十六进制串后加大写字母H: ‘0123456789ABCDEF’H
- 带小数点的小数形式不能在ASN.1中直接使用,在ASN.1中实数实际定义为三个整数:尾数、基数和指数。
- 注释以两个连字符“–”开始,结束于行的结尾或者该行中另一个双连字符。
- 如同大多数计算机语言,ASN.1不对空格、制表符、换行符和注释做翻译。但是在定义符号(或者分配符号Assignment)“::=”中不能有分隔符,否则不能正确处理。
3.2 类型定义
<新类型的名字> ::= <类型描述>
- <新类型的名字>是一个以大写字母开头的标识符;
- <类型描述>是基于内建类型或在其它地方定义的类型。
Married ::= BOOLEAN
Age ::= INTEGER
Picture ::= BIT STRING
Form ::= SEQUENCE{
name PrintableString,
age Age,
married Married,
marriage-certificate Picture OPTIONAL
}
Payment-method ::= CHOICE {
check Check-number,
credit-card SEQUENCE{
number Card-number,
expiry-date Date
}
}
注意:
1.在SEQUENCE和SET等(是所有组合类型的)定义中,最后一个成员结尾没有逗号“,”。
2.为了接收方能正确解码,发送方为每个值的类型附加一个数,称为tag,在描述中以“[]”标识。
缺省情况下,编码器会使用universal的tag。很多时候,缺省情况下不能消除所有的模糊性,有必要明确指出各成员的tag。
Coordinates ::= SET{
x [1] INTEGER,
y [2] INTEGER,
z [3] INTEGER OPTIONAL
}
Afters ::= CHOICE{
cheese [0] PrintableString,
dessert [1] PrintableString
}
3.允许递归式的类型分配(Assignment),但我们应当保证其中包含至少一个非递归的值,因为编码规则无法处理无限的值。
当然,绝大多数结构类型的成员都终结于简单类型。
为了准确描述一个类型,我们需要对值的集合进行一定的限制。这用到子类型约束,在类型之后用圆括号进行标识。
Lottery-number ::= INTERGER(1..49)
Lottery-draw ::= SEQUENCE SIZE(6) OF Lottery-number
Upper-case-words ::= IA5String (FROM(“A”..”Z”))
Phone-number ::= NumericString (FROM(“0”..”9”))(SIZE(10))
Coordinates-in-plan ::= Coordinates (WITH COMPONENTS {…, z ABSENT})
3.3 值定义
<新的值的名字> <该值的类型> ::= <值描述>
- <新的值的名字>是以小写字母开头的标识符;
- <该值的类型>可以是一个类型的名字,也可以是类型描述;
- <值描述>是基于整数、字符串、标识符的组合。
counter Lottery-number ::= 45
sextuple Lottery-draw ::= { 7, 12, 23, 31, 33, 41 }
pair Coordinates ::= { x 5, y -3 }
son-choice Afters ::= dessert:"profiterolles"
date Date ::= "20000824"
upper-bound INTEGER ::= 12
Interval ::= INTEGER(0..upper-bound)
default-value Interval ::= 0
Pair ::= SEQUENCE {
first [0] Interval DEFAULT default-value,
second [1] Interval DEFAULT default-value
}
3.4 信息对象类和信息对象
<信息对象类> ::= CLASS <类描述>
WITH SYNTAX <信息描述>
OPERATION ::= CLASS {
&number INTEGER UNIQUE,
&Argument-type,
&Return-result-type
}
WITH SYNTAX {
OPERATION NUMBER &number
TAKES AN ARGUMENT OF TYPE &Argument-type
AND RETURNS A VALUE OF TYPE &Return-result-type
}
解释:
1.域&number以小写字母开头,后面跟了类型INTEGER。这个整数值用作信息的标识符,因为后面加了UNIQUE关键字。
2.域&Argument-type和&Return-result-type以大写字母开头,后面什么都没有跟。他们是一些ASN.1类型的引用。
3.WITH SYNTAX块定义了一个用户友好的语法,说明了这个类的成员。
上述信息对象类的一个对象定义如下:
plan-projection OPERATION ::= {
OPERATION NUMBER 12
TAKES AN ARGUMENT OF TYPE Coordinates
AND RETURNS A VALUE OF TYPE Coordinates-in-plan
}
一个给定类的所有对象,可以在描述中收集到一个对象集合中,如下:
SupportedOperations OPERATION ::= {
plan-projection | translation | symmetry, ...
}
注意:
1.和对象不同,对象集合以大写字母开头。
2.字符“…”表明新的对象可以由通讯中的机器动态加入。
3.信息对象永远不会被编码,传递他们各项信息的唯一方法是在一个类型中引用他们。
我们用上面这个信息对象集合来约束一个结构类型:
Execute-operation ::= SEQUENCE {
code OPERATION.&number({SupportedOperations}),
argument OPERATION.&Argument-type
({SupportedOperations}{@code})
}
Receive-result ::= SEQUENCE {
code OPERATION.&number({SupportedOperations}),
result OPERATION.&Return-result-type
({SupportedOperations}{@code})
}
这段晦涩的描述,声明了这样一种情况:
Execute-operation操作它的编号在code成员中,当其argument发送给对方时,一定要满足域&Argument-type的类型。链接(或者表约束)“@code”说明这个参数是依赖于操作的。
对方返回的Receive-result也有类似约束。
3.5 模块定义
<模块名字> DEFINITIONS <缺省Tag> ::=
BEGIN
EXPORTS<导出描述>
IMPORTS<导入描述>
<模块体描述>
END
PKIX1Explicit88 { iso(1) identified-organization(3) dod(6) internet(1)
security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-explicit(18) }
DEFINITIONS EXPLICIT TAGS ::=
BEGIN
...
--注释 certificate and CRL specific structures begin here
Certificate ::= SEQUENCE {
tbsCertificate TBSCertificate,
signatureAlgorithm AlgorithmIdentifier,
signature BIT STRING }
TBSCertificate ::= SEQUENCE {
version [0] Version DEFAULT v1,
serialNumber CertificateSerialNumber,
… }
Version ::= INTEGER { v1(0), v2(1), v3(2) }
CertificateSerialNumber ::= INTEGER
…
END
4. BER
BER(Basic Encoding Rules):ASN.1中最早定义的编码规则。在具体系统中,我们需要用具体的编码规则将ASN.1语法表示的抽象数据转换成具体的比特流。SNMP(简单网络管理协议)使用的编码方法是BER。
4.1 三元组规则
三元组规则:<tag, length, value>,或者称为TLV,其中:
- tag,是类型的标识符,在ASN.1中每种类型的tag是唯一的;
- 实际编码中,每个类型的tag实际上是一个值对:<tagging class, number>。
- 有四种tagging class:UNIVERSAL,context-specific,APPLICATION和PRIVATE。
- 这种方式实际提供了不同的Tag空间。在一个上下文中,如果Tagging Class不同,则相同number的两个Tag也是不同的。
- APPLICATION和PRIVATE 已不推荐使用。
- Tag是一个或若干个八位组
- 当Tag不大于30时,Tag只在一个八位组中编码;
- 当Tag大于30时,则Tag在多个八位组中编码。在多个八位组中编码时,第一个八位组后五位全部为1,其余的八位组最高位为1表示后续还有,为0表示Tag结束。Tag的值需要将上图中黄色部分拼接后才能得到。
- Length,是编码数据value的字节数
- Length的三种形式:
- 采用定长方式,当长度不大于127个八位组时,Length只在一个八位组中编码;当长度大于127时,在多个八位组中编码,此时第一个八位组低七位表示的是Length所占的长度,后续八位组表示Value的长度。
- 采用不定长方式时,Length所在八位组固定编码为0x80,但在Value编码结束后以两个0x00结尾。这种方式使得可以在编码没有完全结束的情况下,可以先发送部分消息给对方。
- Length的三种形式:
- value是实际数据的编码
- BER传输语法的格式三元组,其中V还可以是TLV三元组
- BER传输语法是基于八位组(为了避免不同系统上的混淆,没有采用Byte为单位,而是采用octet ,Byte和octet都表示为8 bits,但是严格意义上来讲,octet才是严格意义上的8 bits,而历史上的Byte其实可以表示为4 bits ~ 10 bits,只不过现在的计算机环境下,已经默认了Byte为8 bits)。
- BER是大端编码,即big-endian(所谓的大端模式,是指数据的高字节,保存在内存的低地址中,而数据的低字节,保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放)
4.2 BER编码规则的属性
- BER编码规则是机器无关的:通讯应用可以很容易支持大端和这种编码格式;而且能支持各种不同的整数长度。
- BER的传输语法是十分冗长的:T和L很多情况下都是可以省略的,但是这种冗余信息一些情况下也有显著的优势,它能很好的保藏抽象语法结构,BER传输语法能容易升级而且向上兼容。
- BER传输语法能容易升级而且向上兼容。如每个类型都可以用CHOICE来代替。
5. ASN.1View 对编码文件分析
任何ASN.1编码都是以两个字节开始(或者八位位组,含有8个二进制位),不管什么类型,它们都是通用的。第一个字节是类型标识符,也包含一些修正位;第二个字节是长度。
5.1 头字节
-
类别位
类别位 由两位 bit8-bit7 表示,用来描述数据将要解释的上下文
位8 位7 类别 0 0 通用(Universal) //最常用 0 1 应用(Application) 1 0 上下文特定(ContextSpecific) 1 1 专用(Private)
-
结构化位
- 表示一个给定的编码是否是相同类型的多种编码的结构化。结构化元素是容器类型必需的,因为在逻辑上,它们只是其他元素的集合。
- 结构化元素有自己的头字节和长度字节,之后是元素各个要素组件的单独编码。也就是说,这些要素组件是独立地可解码ASN.1数据类型。严格的说,容器类是唯一允许使用结构化位的数据类型。这是因为对于其他数据类型,给定内容,只允许一种编码。所以其他所有数据类型的结构化位都为0。
- bit6 表示是否为结构类型(1位结构类型);0则表明编码类型是简单类型。
-
原始类型位
当 bit8-bit7 为 universal(00)时,bit5-bit1的值表示不同的universal的值:ASN.1头字节的低5位定义了32种ASN.1的原始类型
标记(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 [统一全球时间格式] [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
-
当 bit8-bit7 为 context-specific(10)时,bit5-bit1的值表示特殊内容:
- [0] –- 表示证书的版本
- [1] –- issuerUniqueID,表示证书发行者的唯一id
- [2] –- subjectUniqueID,表示证书主体的唯一id
- [3] –- 表示证书的扩展字段
-
-
eg:
- SEQUENCE 类型数据块,其TAG类型位UNIVERSAL(00),属于结构类型(1),TAG值为16(10000)所以其类型标示字段值为(00110000),即为0x30。
- 证书扩展字段类型的数据块,TAG类型为(10),属结构类型(1),TAG的值为3(00011),所以其类型标示字段值为(10100011),即为0xA3。
5.2 数据块的长度
长度字段,有两种编码格式。
- 若长度值小于等于127,则用一个字节表示,bit8 = 0,bit7-bit1 存放长度值;
- 若长度值大于127,则用多个字节表示,可以有2到127个字节。第一个字节的第8位为1,其它低7位给出后面该域使用的字节的数量,从该域第二个字节开始给出数据的长度,高位优先。
- 还有一种特殊情况,这个字节为0x80,表示数据块长度不定,由数据块结束标识结束数据块。结束标示字段,两个字节(0x00 00),只有在长度值为不定时才会出现。
- 对象标识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。
- eg:81010 = 610*12810+4210 ,其中{6,42}在二进制中是7位,需要在除最后一位以外,在bit8设置位1,最后一位bit8设置为0,所以6,二进制0000110->10000110,对应16进制为0x86,42->0101010->00101010,对应16进制为0x2a,所以810编码为0x86 0x2a
- eg:11354910 = 610 * 1282 + 11910 * 12810 + 13 10 ,{6,119,13} -> {0000110,1110111,0001101} ->{10000110,11110111,00001101} ->{0x86,0xf7,0x0d}
5.3 数据块的值
存放数据块的值,具体编码随数据块类型不同而不同。
5.4 对 .cer 文件分析
30 82 03 fe --0x30,对应十进制48,对应二进制00110000,即bit8-bit7:00 universal类;bit6:1 结构类型;bit5-bit1:10000 对应十进制16,即sequence,0x82 sequence值的length的长度为两个字节, length为 0x03 fe 对应十进制为1022个字节,
30 82 02 e6 --内容1,sequence,length为 0x02 e6 即742个字节
a0 03 --内容1.1,0xa0对应十进制160,对应二进制10100000,即bit8-bit7:10 ContextSpecific类;bit6:1 结构类型;bit5-bit1:00000 对应十进制0,即表示证书的版本,0x03值的length为3个字节
02 01 --表示context的内容即1.1.1 tag为0x02,即integer,l为1
02 --integerv为2
02 0c --内容1.2 tag为0x02,integer,l为0x0c即12个字节
49 ea 00 00 00 00 0e 4e f2 60 ba 53 //integer 的 v为0x49 ea 00 00 00 00 0e 4e f2 60 ba 53
30 0d --内容1.3 sequence类型,0x0d即13个字节的长度
06 09 --内容1.3.1 tag0x06 为object identifier [相应于一个对象的独特标识数字],l为9,
2a 86 48 86 f7 0d 01 01 0b --v为
2a = 1*40+2,前两个为 1,2
86 48 = 6*128 + 72 = 840
86 f7 0d = 对应整数 113549
01 = 1
01 = 1
0b = 11
所以v为 1.2.840.113549.1.1.11 ---对照算法SHA256
05 00 --内容1.3.2 tag为NULL l为0,v为null
30 81 89 --内容1.4 sequence类型,0x89的长度,即137字节
31 0b --内容1.4.1 0x31,对应十进制49,对应二进制00110001,即bit8-bit7:00 universal类;bit6:1 结构类型;bit5-bit1:10001 对应十进制11,即set,长度11字节
30 09 --1.4.1.1 sequence类,9个字节
06 03 --属性0x06 即oid,长度3个字节
55 04 06 -- 0x55 = 85 = 2*40+5,前两位 {2,5} 0x04 = 4 0x06 = 6 所以oid={2.5.4.6},对应countryName
13 02 --属性0x13,19-PrintableString,
43 4e - 0x43对应ascii编码 C,0x4e对应ascii编码 N,所以value 为 CN
31 0F --内容1.4.2 set类型,15个字节
30 0D --1.4.2.1 sequence 13个字节
06 03 --属性0x06 即oid,长度3个字节
55 04 08 -- oid={2.5.4.8},对应 stateOrProvienceName
0c 06 --属性0x0c,12-UTF8String,6个字节
e4 b8 8a e6 b5 b7 - 0xe4 b8 8a 对应UTF-8编码 上,0xe6 b5 b7对应UTF-8编码 海,所以value 为 上海
31 12 --内容1.4.3 set类型,18个字节
30 10 --1.4.3.1 sequence 16个字节
06 03 --属性0x06 即oid,长度3个字节
55 04 07 -- oid={2.5.4.7},对应 localityName
0c 09 --属性0x0c,12-UTF8String,9个字节
e4 b8 8a e6 b5 b7 e5 b8 82 - 0xe4 b8 8a 对应UTF-8编码 上,0xe6 b5 b7对应UTF-8编码 海,0xe5 b8 82对应UTF-8编码 市,所以value 为 上海市
31 15 --内容1.4.4 set类型,21个字节
30 13 --1.4.4.1 sequence 19个字节
06 03 --属性0x06 即oid,长度3个字节
55 04 0B -- oid={2.5.4.11},对应 organizationalUnitName
0c 0c --属性0x0c,12-UTF8String,12个字节
e6 a0 bc e5 b0 94 e8 bd af e4 bb b6 --解析对应UTF-8编码 ,v为格尔软件
31 0f --内容1.4.5 set类型,15个字节
30 0d --1.4.5.1 sequence 19个字节
06 03 --属性0x06 即oid,长度3个字节
55 04 03 -- oid={2.5.4.3},对应 commonName
0c 06 --属性0x0c,12-UTF8String,6个字节
4b 6f 61 6c 43 61 --解析对应ascii编码 ,v为KoalCa
30 1e --内容1.5 sequence类型,30字节
17 0d -- tag为 0x17,23,UTCTime类型 13个字节
32 31 30 37 31 38 31 36 30 30 30 30 5a --解析对应ascii编码 ,v为210718160000Z
17 0d -- tag为 0x17,23,UTCTime类型 13个字节
33 30 30 37 32 32 31 35 35 39 35 39 5a --解析对应ascii编码 ,v为300722155959Z
30 41 --内容1.6 sequence类型,65字节
31 0b --1.6.1 tag set类型,11字节
30 09 --1.6.1.1 sequence类型 9个字节
06 03 --tag oid 3个字节
55 04 06 -- oid ={2.5.4.6},对应countryName
13 02 --tag PrintableString 2个字节
43 4e -- 解析ascii编码,v = CN
31 1e --1.6.2 tag set类型,30字节
30 1c --1.6.2.1 sequence类型 28个字节
06 09 --tag oid 9个字节
2a 86 48 86 f7 0d 01 09 01 -- oid ={1.2.840.113549.1.9.1},对应emailAddress
16 0f --tag IA5String 15个字节
77 61 6e 67 6c 6b 40 6b 6f 61 6c 2e 63 6f 6d -- 解析ascii编码,v = wanglk@koal.com
31 12 --1.6.3 tag set类型,18字节
30 10 --1.6.3.1 sequence类型 16个字节
06 03 --tag oid 3个字节
55 04 03 -- oid ={2.5.4.3},对应commonName
0c 09 --tag UTF8String 9个字节
e7 8e 8b e8 b7 af e5 ae bd -- 解析UTF-8编码,v = 王路宽
30 82 01 22 --内容1.7 sequence类型,0x01 22 ,290字节
30 0d --tag sequence类型 13字节
06 09 --tag oid 9个字节
2a 86 48 86 f7 0d 01 01 01 = oid ={1.2.840.113549.1.1.1} 对应 RSA加密算法
05 00 --tag NULL
03 82 01 0f -- tag为BIT STRING ,0x01 0f字节,即271字节
00 30 82 01 0a 02 82 01 01 00 8b 6b cb a4 d9 0a
80 8b 8f bc 3f 32 bb 4b f1 c5 d2 ad 44 80 63 d3
c9 59 c3 46 6e 8c 96 59 80 93 c9 7c 1b 4e 02 51
0f ca fd 73 aa 42 11 fd d7 47 c9 2b b1 7d 7d 4a
3a 38 e9 7b 25 4d b1 b2 df 2c 71 b7 47 99 21 81
28 62 f2 71 1c c8 40 58 8d 92 24 59 77 fe 1a 0e
d5 22 a9 1a 40 50 9b f8 cd 8a 7e 90 65 5b 5e f5
fb ad c1 fa ab 70 3c 99 ce ae e8 19 6b 28 ab 6b
da bd 9d e8 b6 09 50 82 84 50 f0 d9 96 29 09 c4
e6 81 63 fa d4 ac f9 1e b3 77 3d 93 14 81 8f 32
53 2b 9a a2 5b f1 c2 04 bd ac d5 02 a3 a3 2f d0
af 28 6b 62 60 d9 fb 2d 4b 38 da b2 41 c6 79 25
8e 3d a9 53 fc 32 cb 9c ca 0f 6c 59 22 03 81 d9
49 f4 ff 4f 59 c2 3a ff 2f d8 54 7d a9 c9 a7 06
76 ca d0 01 ad 10 c9 5f 93 d3 1a c3 32 75 74 2f
0a a4 30 7e 12 a0 cc e6 2a ce 11 57 97 51 ef 6f
62 8e d9 6a 40 0b 5a c1 1e 21 02 03 01 00 01