X.509是公钥基础设施(PKI)的标准格式。X.509证书就是基于国际电信联盟(ITU)制定的X.509标准的数字证书。X.509证书主要用于识别互联网通信和计算机网络中的身份,保护数据传输安全。X.509证书无处不在,比如我们每天使用的网站、移动应用程序、电子文档以及连接的设备等都有它的身影。
X.509证书的结构优势在于它是由公钥和私钥组成的密钥对而构建的。公钥和私钥能够用于加密和解密信息,验证发送者的身份和确保消息本身的安全性。基于X.509的PKI最常见的用例是使用SSL证书让网站与用户之间实现HTTPS安全浏览。X.509协议同样也适用于应用程序安全的代码签名、数字签名和其他重要的互联网协议。
准备证书
下载support.microsoft.com的证书
得到的证书的内容为:
-----BEGIN CERTIFICATE----- |
得到base64解析后的内容(HEX进制)为
3082086E30820656A00302010202133301C9F75BF51894993E166C61000001C9F75B300D06092A864886F70D01010C0500305D310B3009060355040613025553311E301C060355040A13154D6963726F736F667420436F72706F726174696F6E312E302C060355040313254D6963726F736F667420417A7572652052534120544C532049737375696E67204341203034301E170D3235303231393039323632355A170D3235303831383039323632355A306C310B3009060355040613025553310B30090603550408130257413110300E060355040713075265646D6F6E64311E301C060355040A13154D6963726F736F667420436F72706F726174696F6E311E301C06035504031315737570706F72742E6D6963726F736F66742E636F6D30820122300D06092A864886F70D01010105000382010F003082010A0282010100B344487DC7EBC07672500D5A05E069BA37C143864142B4BE0EB932DB0AAB559C99FCC697F647F8F10C90790C403B2AE273AB8307335B869281EF7C0C49BC0B42BF806EAF071705138881A62252856C811DD0B2D824940893232330088D5E864CAE4842D37415B851E4FEEA75452CB6F203539DB1DC2FAFE87C1046BF21DDD62048D59017597EE6339ED2B4274344EBEC050340D60C0F8303956269BF4DC9F3F9720BAF1AEEF325C85482C67DAABB3CDF0099DF493C554CF745674F7B884DCE12F6278097CD957B7D0D0A9F306C93574A493C54573150B5C6DF4DE9D913B92C504A1B22E7B841F051D16DF0FDC08909955AFD943160BAF1CAFB72C99C3F3164950203010001A3820416308204123082017D060A2B06010401D6790204020482016D048201690167007500DDDCCA3495D7E11605E79532FAC79FF83D1C50DFDB003A1412760A2CACBBC82A000001951D90DE34000004030046304402206BC4F94795710AABCA93992DF628D707C199D7C37000EBC4FE27BF73CEC40F6C02202BC7EC88E363BA169BE0CE35D6F26482DEE89C745598020187F468FA1A918A2B0076007D591E12E1782A7B1C61677C5EFDF8D0875C14A04E959EB9032FD90E8C2E79B8000001951D90DDEF000004030047304502207287C9CA3946FBB038768CC9FD1AB23AF277294D7CB9CC2BBC882ACC5BEFC81802210097816A753589A70A69CC285A7A6CD76146F1B8A047B8E560E7F683CEB116E80D0076001A04FF49D0541D40AFF6A0C3BFF1D8C4672F4EECEE234068986B17402EDC897D000001951D90DE5200000403004730450220081A934EDB5C292F509B1F0294A1D194105F549CE9C9FE9199E86D4290BA2E83022100B7337E5305E5CFB5D86F0D447AEAC7B8C8F49543C308D4E99BA17DDF239FF644302706092B060104018237150A041A3018300A06082B06010505070302300A06082B06010505070301303C06092B0601040182371507042F302D06252B060104018237150887BDD71B81E7EB4682819D2E8ED00C87F0DA1D5D82ABE73087EDF11F02016402012D3081B406082B060105050701010481A73081A4307306082B060105050730028667687474703A2F2F7777772E6D6963726F736F66742E636F6D2F706B696F70732F63657274732F4D6963726F736F6674253230417A757265253230525341253230544C5325323049737375696E67253230434125323030342532302D253230787369676E2E637274302D06082B060105050730018621687474703A2F2F6F6E656F6373702E6D6963726F736F66742E636F6D2F6F637370301D0603551D0E041604143A7C1CB9F7B1ACC8F291FA84B4F86D5D5F064CF3300E0603551D0F0101FF0404030205A030200603551D11041930178215737570706F72742E6D6963726F736F66742E636F6D300C0603551D130101FF04023000306A0603551D1F04633061305FA05DA05B8659687474703A2F2F7777772E6D6963726F736F66742E636F6D2F706B696F70732F63726C2F4D6963726F736F6674253230417A757265253230525341253230544C5325323049737375696E67253230434125323030342E63726C30660603551D20045F305D3051060C2B0601040182374C837D01013041303F06082B060105050702011633687474703A2F2F7777772E6D6963726F736F66742E636F6D2F706B696F70732F446F63732F5265706F7369746F72792E68746D3008060667810C010202301F0603551D230418301680143B70D153E976259D60A8CA660FC69BAE6F54166A301D0603551D250416301406082B0601050507030206082B06010505070301300D06092A864886F70D01010C050003820201005716D5B4CADD4002262CF7FF4677B618298FCB3858E287990F99A25DC7B3415300C63971EBA68A57549A061FFE3316F32D4177A842653F31439E89F55BF549EB0B8109FF65ED3EDB29AFA31688A8ED4A91DDF54B2D5DF248D05480C1D52FA7BC879763C55B2684DC16E7DC4CEA9D0169C246BF22A730867E7921DDA9F90746E9F18E4023072CC03A32C7CBEA36A3F379FA98F1429FEE0607D00F887784C21BE6E8C0E929FE4B9826AC71A7EC33E4DF025C37E13DEB813E881DF52AF2B0700BFF142D35FDCBAFEB54F5C39BE222A0F1557665AB97EFB05CDC323D972D2F313486A4B0C9680BD8E6379E591834DB685856E4D31CA051CEF6C26D07274E5F5DE3E7F945446C6EDF1E8CE4F1653DE91B037E14CEDB70786DB5D32EB89EA6863CB0319142B904577459F20C1CA7CE53B0E06A2CF2B9E4E524B62D17B48F48BAB6A0232081747A4F05212FCC5A5A736FFE0C4FE36BF66542D5FFB45850F91C227743A827E9A93561E8A48214ECEAA969C77FD63EE212E414D5ED1AF629F48AEBD71C8DC4D22DE94470A8A829DDDD1A44B470B68A8080B37BCB741E508BF5349623E818A52FD36DFD7BDC6E4D81882FD44B26D79BA448C4AC7BC80745724BA9D4B0A1B083C2A7177FDDC81BC02A2A460AE3F0A58B8677A6252EEB63C1CDECDF9809E850BE0ED158B7FE20A182424A283E51AE9CB1E4A87843E58C4C016400EFC1DDFF2F |
证书结构
X.509证书是基于ASN.1(Abstract Syntax Notation One)标准定义的,其结构遵循ASN.1的编码规则(通常使用DER编码)。要手动解析X.509证书,需要结合X.509的ASN.1规范和DER编码规则,逐步解析证书的二进制数据。
X.509证书的ASN.1结构
Certificate ::= SEQUENCE { |
X.509证书基本部分
版本号:标识证书的版本(版本1、版本2或是版本3)。
序列号:标识证书的唯一整数,由证书颁发者分配的本证书的唯一标识符。
签名:用于签证书的算法标识,由对象标识符加上相关的参数组成,用于说明本证书所用的数字签名算法。例如,SHA-1和RSA的对象标识符就用来说明该数字签名是利用RSA对SHA-1杂凑加密。
颁发者:证书颁发者的可识别名(DN)。
有效期:证书有效期的时间段。本字段由”Not Before”和”Not After”两项组成,它们分别由UTC时间或一般的时间表示(在RFC2459中有详细的时间表示规则)。
主体:证书拥有者的可识别名,这个字段必须是非空的,除非你在证书扩展中有别名。
主体公钥信息:主体的公钥(以及算法标识符)。
颁发者唯一标识符:标识符—证书颁发者的唯一标识符,仅在版本2和版本3中有要求,属于可选项。
主体唯一标识符:证书拥有者的唯一标识符,仅在版本2和版本3中有要求,属于可选项。
X.509证书扩展部分
可选的标准和专用的扩展(仅在版本2和版本3中使用),扩展部分的元素都有这样的结构:
Extension ::= SEQUENCE { |
- extnID:表示一个扩展元素的OID
- critical:表示这个扩展元素是否极重要
- extnValue:表示这个扩展元素的值,字符串类型。
扩展部分包括:
- 发行者密钥标识符:证书所含密钥的唯一标识符,用来区分同一证书拥有者的多对密钥。
- 密钥使用:一个比特串,指明(限定)证书的公钥可以完成的功能或服务,如:证书签名、数据加密等。
如果某一证书将 KeyUsage 扩展标记为“极重要”,而且设置为“keyCertSign”,则在 SSL 通信期间该证书出现时将被拒绝,因为该证书扩展表示相关私钥应只用于签写证书,而不应该用于 SSL。
CRL分布点:指明CRL的分布地点。
- 私钥的使用期:指明证书中与公钥相联系的私钥的使用期限,它也有Not Before和Not After组成。若此项不存在时,公私钥的使用期是一样的。
- 证书策略:由对象标识符和限定符组成,这些对象标识符说明证书的颁发和使用策略有关。
- 策略映射:表明两个CA域之间的一个或多个策略对象标识符的等价关系,仅在CA证书里存在。
- 主体别名:指出证书拥有者的别名,如电子邮件地址、IP地址等,别名是和DN绑定在一起的。
- 颁发者别名:指出证书颁发者的别名,如电子邮件地址、IP地址等,但颁发者的DN必须出现在证书的颁发者字段。
- 主体目录属性:指出证书拥有者的一系列属性。可以使用这一项来传递访问控制信息。
解析流程
以下是手动解析证书的步骤:
(1)读取证书的二进制数据
证书通常是Base64编码的PEM格式。首先需要将PEM格式转换为二进制DER格式:
- 去掉
-----BEGIN CERTIFICATE-----
和-----END CERTIFICATE-----
。 - 将Base64解码为二进制数据。
(2)解析顶层SEQUENCE
证书的顶层是一个SEQUENCE,包含三个部分:
tbsCertificate
(证书主体)signatureAlgorithm
(签名算法)signatureValue
(签名值)
根据DER的TLV结构:
- 第一个字节是类型标签(Tag),
0x30
表示SEQUENCE。 - 接下来的字节是长度(Length),可能是单字节或多字节。
- 根据长度读取值(Value),即证书的完整内容。
(3)解析 tbsCertificate
tbsCertificate
是一个SEQUENCE,包含多个字段:
- 版本(Version):可选字段,标签为
0xA0
,值为整数。 - 序列号(SerialNumber):标签为
0x02
,值为整数。 - 签名算法(Signature Algorithm):标签为
0x30
,值为SEQUENCE,包含算法标识符和参数。 - 颁发者(Issuer):标签为
0x30
,值为SEQUENCE,包含多个RDN(Relative Distinguished Name)。 - 有效期(Validity):标签为
0x30
,值为SEQUENCE,包含notBefore
和notAfter
。 - 主题(Subject):标签为
0x30
,值为SEQUENCE,包含多个RDN。 - 公钥信息(SubjectPublicKeyInfo):标签为
0x30
,值为SEQUENCE,包含算法标识符和公钥。 - 扩展字段(Extensions):可选字段,标签为
0xA3
,值为SEQUENCE,包含多个扩展。
(4)解析每个字段
版本(Version):
- 标签:
0xA0
(上下文特定的标签,表示版本)。 - 值:整数,
0
表示v1,1
表示v2,2
表示v3。
- 标签:
序列号(SerialNumber):
- 标签:
0x02
(INTEGER)。 - 值:证书的唯一序列号。
- 标签:
签名算法(Signature Algorithm):
- 标签:
0x30
(SEQUENCE)。 - 值:包含算法标识符(OID)和参数。
- 标签:
颁发者(Issuer):
- 标签:
0x30
(SEQUENCE)。 - 值:包含多个RDN,每个RDN是一个SET,包含类型和值。
- 标签:
有效期(Validity):
- 标签:
0x30
(SEQUENCE)。 - 值:包含
notBefore
和notAfter
,通常是UTCTime或GeneralizedTime。
- 标签:
主题(Subject):
- 标签:
0x30
(SEQUENCE)。 - 值:包含多个RDN,每个RDN是一个SET,包含类型和值。
- 标签:
公钥信息(SubjectPublicKeyInfo):
- 标签:
0x30
(SEQUENCE)。 - 值:包含算法标识符和公钥(BIT STRING)。
- 标签:
扩展字段(Extensions):
- 标签:
0xA3
(上下文特定的标签,表示扩展)。 - 值:SEQUENCE,包含多个扩展,每个扩展是一个SEQUENCE,包含OID、关键性和扩展值。
- 标签:
(5)解析签名算法和签名值
签名算法(signatureAlgorithm):
- 标签:
0x30
(SEQUENCE)。 - 值:包含算法标识符和参数。
- 标签:
签名值(signatureValue):
- 标签:
0x03
(BIT STRING)。 - 值:证书的签名值。
- 标签:
示例解析
以上面证书为例,假设已经转换为DER格式,以下是部分解析过程:
得到证书的内容值
30 82 086E |
解析证书主体TBSCertificate
得到的内容值为:
A0 03 020102 -- **版本(Version)**:可选字段,标签为 `0xA0`,值为整数 |
版本(Version)
定义为:
version [0] EXPLICIT Version DEFAULT v1, |
实际值: 020102
X.509证书版本号在ASN.1结构中通过显式标签的上下文特定字段表示:
显式标签:版本号字段的标签号为
0
(上下文特定),编码为A0
(构造类型,标签号0)。版本值
:版本号从0开始递增:
- v1 → 0(默认值,通常不显式编码)
- v2 → 1
- v3 → 2
因此,0x02 0x01 0x02
的完整编码应为:A0 03 02 01 02
A0
:显式标签(上下文特定,构造类型,标签号0)。03
:后续数据总长度3字节。02 01 02
:INTEGER类型(0x02)、长度1字节(0x01)、值2(0x02)。
为什么
0x02
表示v3?
- X.509版本号从v1开始计数,但ASN.1编码中版本号从0开始:
v1
→ 0(通常省略)v2
→ 1v3
→ 2- 因此,
0x02
(十进制2)对应v3版本。
序列号(SerialNumber)
定义为:
CertificateSerialNumber ::= INTEGER |
实际值: 3301C9F75BF51894993E166C61000001C9F75B
签名算法(Signature Algorithm)
定义为:
AlgorithmIdentifier ::= SEQUENCE { |
实际值:06 09 2A864886F70D01010C 05 00
签名算法值 06092A864886F70D01010C0500
的解析需遵循 ASN.1编码规范 和 X.509标准。以下是分步解析过程:
整体结构拆分
原始值 06092A864886F70D01010C0500
可拆分为两部分:
- 签名算法标识符:
06092A864886F70D01010C
- 参数:
0500
签名算法标识符解析
- 标签(Tag):
06
→ OBJECT IDENTIFIER (OID) 类型。 - 长度(Length):
09
→ 后续数据占 9字节。 - 值(Value):
2A864886F70D01010C
→ OID编码。
OID解码
OID编码规则:将数字序列转换为可变长整数,例如 2A864886F70D01010C
分解如下:
前两个数字:
2A
(十六进制) → 十进制42
→ 分解为1.2
(公式:X = 1
,Y = 42 - 40 = 2
)。后续数字:
864886F70D
→ 解析为840.113549
(RSADSI的OID)3。
0101
→ 分解为1.1
(RSA加密算法标识)。0C
→ 十进制12
→ 表示哈希算法为 SHA-384。
完整OID:1.2.840.113549.1.1.12
,对应 sha384WithRSAEncryption3。
根据RFC文档,常见的签名算法OID包括:
- sha256WithRSAEncryption: 1.2.840.113549.1.1.11
- sha384WithRSAEncryption: 1.2.840.113549.1.1.12
- sha512WithRSAEncryption: 1.2.840.113549.1.1.13
参数解析
- 标签(Tag):
05
→ NULL 类型。 - 长度(Length):
00
→ 无数据。 - 值(Value):无(RSA签名算法通常无参数,显式声明为NULL)。
在X.509证书中,签名算法字段的典型编码示例如下:
SignatureAlgorithm ::= SEQUENCE { |
此处对应:
algorithm = 1.2.840.113549.1.1.12
parameters = NULL
4。
颁发者(Issuer)
定义为:
Name ::= SEQUENCE OF RelativeDistinguishedName |
实际值:
310B3009060355040613025553311E301C060355040A13154D6963726F736F667420436F72706F726174696F6E312E302C060355040313254D6963726F736F667420417A7572652052534120544C532049737375696E67204341203034 |
整体结构拆分
颁发者信息采用 ASN.1 SEQUENCE 结构,包含多个属性项(RDN,Relative Distinguished Name)。按层级拆分如下:
31 0B 3009060355040613025553 |
31
是 SEQUENCE 的标签(Tag),表示一个复合结构。0B
是长度(11字节),后续每个子项同样以31
开头。
逐层解析属性
国家(Country)
30 09 -- SEQUENCE (9字节) |
- OID
2.5.4.6
:表示国家代码。 - 值
55 53
:ASCII解码为US
。
取值说明
- “30”:表示这又是一个SEQUENCE结构(因为前面确定是SEQUENCE类型,这里面可能包含多个SEQUENCE结构来表示不同的属性值对)。
- “09”:表示这个SEQUENCE结构的长度是9个字节。
- “0603550406”:
- “06”:表示OBJECT IDENTIFIER类型。
- “03”:表示这个OBJECT IDENTIFIER的长度是3个字节。
- “550406”:具体的OBJECT IDENTIFIER值,根据标准映射,这里表示 “countryName”(国家名称)。
- “1302”:
- “13”:表示PrintableString类型。
- “02”:表示这个PrintableString的长度是2个字节。
- “5553”:转换为字符是 “US”,即国家名称为美国。
组织(Organization)
30 1C -- SEQUENCE (28字节) |
- OID
2.5.4.10
:表示组织名称。 - 值解码:十六进制
4D69...
→ ASCIIMicrosoft Corporation
。
通用名称(Common Name)
30 2C -- SEQUENCE (44字节) |
- OID
2.5.4.3
:表示通用名称。 - 值解码:十六进制
4D69...
→ ASCIIMicrosoft Azure RSA TLS Issuing CA 04
。
字段对应关系
标签(Tag) | 长度(Length) | 值(Value) | 对应字段 |
---|---|---|---|
30 09 |
9字节 | OID=2.5.4.6, 值=”US” | 国家(Country) |
30 1C |
28字节 | OID=2.5.4.10, 值=”Microsoft Corporation” | 组织(Organization) |
30 2C |
44字节 | OID=2.5.4.3, 值=”Microsoft Azure RSA TLS Issuing CA 04” | 通用名称(Common Name) |
编码逻辑说明
- ASN.1嵌套规则:每个属性通过
SEQUENCE
(标签30
)封装,内部包含OID和值。 - OID编码:
06
表示OBJECT IDENTIFIER,例如2.5.4.6
编码为06 03 55 04 06
2。 - 值类型:
13
表示 PrintableString,用于国家、组织等字段。
这与证书颁发机构(CA)的层级结构一致,符合Microsoft Azure证书的命名规范15
有效期(Validity)
定义为:
Validity ::= SEQUENCE { |
实际值:
17 0D 3235303231393039323632355A |
有效期值 170D3235303231393039323632355A170D3235303831383039323632355A
的解析步骤如下:
整体结构拆分
该值为 两个UTCTime字段的ASN.1编码,对应证书的 Not Before(生效时间) 和 Not After(失效时间):
170D3235303231393039323632355A // Not Before |
逐字段解析
Not Before
标签(Tag):
17
→ ASN.1中表示 UTCTime类型(通用协调时间)。长度(Length):
0D
(十进制13)→ 后续数据占13字节。值(Value):
32 35 30 32 31 39 30 39 32 36 32 35 5A
;转换为ASCII字符串:250219092625Z
按UTCTime格式YYMMDDHHMMSSZ
解析:
25
→ 年份 202502
→ 月份 2月19
→ 日期 19日09
→ 小时 09时26
→ 分钟 26分25
→ 秒 25秒Z
→ UTC时区
最终时间:2025-02-19 09:26:25 UTC
Not After**
标签(Tag):
17
→ UTCTime类型。长度(Length):
0D
→ 13字节。值(Value):
32 35 30 38 31 38 30 39 32 36 32 35 5A
转换为ASCII字符串:250818092625Z
解析为:
25
→ 2025年08
→ 8月18
→ 18日09:26:25
最终时间:2025-08-18 09:26:25 UTC
关键编码规则
- UTCTime格式:用于表示2000年后的日期,格式为
YYMMDDHHMMSSZ
(年份后两位+月日时分秒+时区)。 - ASN.1编码规则:
- 标签
17
表示UTCTime类型。 - 长度字段
0D
对应十六进制的13,表示后续13字节为时间数据。 - 时间字符串末尾的
5A
(ASCII字符Z
)表示UTC时区(零时差)。
- 标签
证书有效期总结
- 生效时间(Not Before):2025年2月19日 09:26:25
- 失效时间(Not After):2025年8月18日 09:26:25
- 总有效期:约6个月(与证书颁发策略相关)1。
主题(Subject)
定义为:
Name ::= SEQUENCE OF RelativeDistinguishedName |
实际值
310B3009060355040613025553310B30090603550408130257413110300E060355040713075265646D6F6E64311E301C060355040A13154D6963726F736F667420436F72706F726174696F6E311E301C06035504031315737570706F72742E6D6963726F736F66742E636F6D |
主题(Subject)解析步骤
主题字段的十六进制值 310B3009060355040613025553...
表示一个 ASN.1编码的集合(SET),包含多个相对可分辨名称(RDN)。以下是逐层解析过程:
整体结构拆分
原始值可拆分为多个 RDN(Relative Distinguished Name),每个RDN由 属性类型(OID) 和 属性值 组成。完整结构如下(以国家、州、地区、组织、通用名称为例):
31 0B 30 09 06 03 55 04 06 13 02 55 53 // 国家(C) |
字段解析(按RDN顺序)
国家(Country, C)
- 编码:
310B3009060355040613025553
- 标签:
0x31
(SET类型) - 长度:
0x0B
(11字节) - 嵌套结构:
- OID:
06 03 55 04 06
→2.5.4.6
(国家代码) - 值类型:
0x13
(打印字符串) - 值:
55 53
→US
1
- OID:
州/省(State/Province, ST)
- 编码:
310B3009060355040813025741
- OID:
06 03 55 04 08
→2.5.4.8
(州代码) - 值:
57 41
→WA
(华盛顿州)
地区(Locality, L)
- 编码:
3110300E060355040713075265646D6F6E64
- OID:
06 03 55 04 07
→2.5.4.7
(地区代码) - 值:
5265646D6F6E64
→Redmond
(雷德蒙德市)
组织(Organization, O)
- 编码:
311E301C060355040A13154D6963726F736F667420436F72706F726174696F6E
- OID:
06 03 55 04 0A
→2.5.4.10
(组织代码) - 值:
4D6963726F736F667420436F72706F726174696F6E
→Microsoft Corporation
1
通用名称(Common Name, CN)
- 编码:
311E301C06035504031315737570706F72742E6D6963726F736F66742E636F6D
- OID:
06 03 55 04 03
→2.5.4.3
(通用名称) - 值:
737570706F72742E6D6963726F736F66742E636F6D
→support.microsoft.com
(微软支持域名)
关键字段对应关系
字段缩写 | ASN.1 OID | 标签类型 | 值编码示例 | 实际值 |
---|---|---|---|---|
C | 2.5.4.6 |
SET | 0x55 0x53 |
US(美国) |
ST | 2.5.4.8 |
SET | 0x57 0x41 |
WA(华盛顿州) |
L | 2.5.4.7 |
SET | 0x52 0x65 0x64 0x6D... |
Redmond(雷德蒙德市) |
O | 2.5.4.10 |
SET | 0x4D 0x69 0x63 0x72... |
Microsoft Corporation |
CN | 2.5.4.3 |
SET | 0x73 0x75 0x70 0x70... |
support.microsoft.com |
- 编码规则
- SET类型(0x31):表示一个无序的属性集合。
- SEQUENCE类型(0x30):嵌套在SET中,包含OID和值的组合。
- OID编码:使用
06
标签,长度后接OID的DER编码(如2.5.4.6
→55 04 06
)。 - 字符串编码:
0x13
表示打印字符串(IA5String),直接转换为ASCII值。
公钥信息(SubjectPublicKeyInfo)
定义:
SubjectPublicKeyInfo ::= SEQUENCE { |
实际值:
30 0D 06092A864886F70D010101 0500 |
以下是按照 ASN.1 结构逐字节解析的过程:
解析顶层 SEQUENCE
SubjectPublicKeyInfo
是一个 SEQUENCE,包含两个字段:
algorithm
(算法标识符)subjectPublicKey
(公钥数据)
解析过程:
- Tag:
0x30
(SEQUENCE)。 - Length:
0x82 0x01 0x0F
(表示长度为 271 字节)。 - Value:包含
algorithm
和subjectPublicKey
。
解析 algorithm
algorithm
是一个 SEQUENCE,包含算法标识符和参数。
解析过程:
- Tag:
0x30
(SEQUENCE)。 - Length:
0x0D
(表示长度为 13 字节)。 - Value:包含算法标识符和参数。
解析算法标识符
- Tag:
0x06
(OBJECT IDENTIFIER)。 - Length:
0x09
(表示长度为 9 字节)。 - Value:
0x2A 0x86 0x48 0x86 0xF7 0x0D 0x01 0x01 0x01
。
算法标识符解析:
- OID 值为
1.2.840.113549.1.1.1
,表示 RSA 加密算法。
解析参数
- Tag:
0x05
(NULL)。 - Length:
0x00
(表示长度为 0 字节)。 - Value:无(NULL 类型没有值)。
解析 subjectPublicKey
subjectPublicKey
是一个 BIT STRING,包含公钥的 DER 编码。
解析过程:
- Tag:
0x03
(BIT STRING)。 - Length:
0x82 0x01 0x00
(表示长度为 256 字节)。 - Value:公钥的 DER 编码。
解析 BIT STRING
BIT STRING 的第一个字节是填充位数(通常为 0),后面是实际的公钥数据。
- 填充位数:
0x00
(表示没有填充位)。 - 公钥数据:从第二个字节开始,长度为 255 字节。
解析公钥数据
公钥数据是一个 SEQUENCE,包含模数(modulus)和指数(exponent)。
解析过程:
- Tag:
0x30
(SEQUENCE)。 - Length:
0x82 0x01 0x0A
(表示长度为 266 字节)。 - Value:包含模数和指数。
解析模数(modulus)
- Tag:
0x02
(INTEGER)。 - Length:
0x82 0x01 0x01
(表示长度为 257 字节)。 - Value:模数的二进制表示。
模数值:
00B344487DC7EBC07672500D5A05E069BA37C143864142B4BE0EB932DB0AAB559C99FCC697F647F8F10C90790C403B2AE273AB8307335B869281EF7C0C49BC0B42BF806EAF071705138881A62252856C811DD0B2D824940893232330088D5E864CAE4842D37415B851E4FEEA75452CB6F203539DB1DC2FAFE87C1046BF21DDD62048D59017597EE6339ED2B4274344EBEC050340D60C0F8303956269BF4DC9F3F9720BAF1AEEF325C85482C67DAABB3CDF0099DF493C554CF745674F7B884DCE12F6278097CD957B7D0D0A9F306C93574A493C54573150B5C6DF4DE9D913B92C504A1B22E7B841F051D16DF0FDC08909955AFD943160BAF1CAFB72C99C3F316495 |
解析指数(exponent)
- Tag:
0x02
(INTEGER)。 - Length:
0x03
(表示长度为 3 字节)。 - Value:
0x01 0x00 0x01
。
指数值:
- 指数为
65537
(即0x010001
)。
完整解析过程
原始数据
30 0D 06 09 2A864886F70D010101 0500 0382010F 003082010A0282010100B344487DC7...0203010001 |
整体结构
subjectPublicKeyInfo
是 SEQUENCE,包含两个字段:
- AlgorithmIdentifier(算法标识)
- subjectPublicKey(公钥数据,BIT STRING)
逐步解析
解析最外层 SEQUENCE
- 标签(Type):
0x30
(SEQUENCE,构造类型) - 长度(Length):
0x0D
(13字节) - 值(Value):后续的13字节数据。
解析 AlgorithmIdentifier
06 09 2A864886F70D010101 0500 |
- 标签:
0x06
(OID,基本类型) - 长度:
0x09
(9字节) - 值:
2A864886F70D010101
- 解码:OID
1.2.840.113549.1.1.1
,表示 RSA 加密算法。
- 解码:OID
- 参数(NULL):
- 标签:
0x05
(NULL,基本类型) - 长度:
0x00
(0字节)
- 标签:
解析 subjectPublicKey(BIT STRING)
03 82010F 003082010A0282010100B344487DC7...0203010001 |
- 标签:
0x03
(BIT STRING,基本类型) - 长度:
0x82010F
(后续2字节表示实际长度,0x010F
= 271字节) - 值:
- 未使用位数:
0x00
(通常为0) - 公钥数据:
3082010A0282010100B344487DC7...0203010001
- 未使用位数:
解析公钥数据(BIT STRING 内部)
公钥数据是 SEQUENCE,包含RSA公钥的模数(n)和指数(e)。
解析 SEQUENCE
30 82010A |
- 标签:
0x30
(SEQUENCE,构造类型) - 长度:
0x82010A
(后续2字节表示长度,0x010A
= 266字节)
解析模数(n)
02 820101 00B344487DC7EBC07672500D5A05E069BA37C143...(后续数据) |
- 标签:
0x02
(INTEGER,基本类型) - 长度:
0x820101
(后续2字节表示长度,0x0101
= 257字节) - 值:
- 模数(n):
00B344487DC7EBC07672500D5A05E069BA37C143...
- 注意:前导
0x00
是为了避免将最高位解释为符号位。
- 模数(n):
解析指数(e)
02 03 010001 |
- 标签:
0x02
(INTEGER,基本类型) - 长度:
0x03
(3字节) - 值:
0x010001
(即65537
,RSA的默认指数)。
完整解析结果
subjectPublicKeyInfo ::= SEQUENCE { |
证书主体的扩展字段段
定义:
extensions [3] EXPLICIT Extensions OPTIONAL -- 证书扩展段(可选),只在证书版本3中才有 |
- extnID:表示扩展项的唯一标识符(OID),用于标识扩展的类型。
- critical:一个布尔值,表示该扩展是否是关键扩展。如果为
TRUE
,则表示该扩展必须被理解并处理,否则证书应被视为无效。默认值为FALSE
。 - extnValue:扩展项的具体值,通常是一个OCTET STRING,表示扩展的实际数据。
在ASN.1编码中,每个字段都有一个标签(Tag),用于标识字段的类型。标签的编码遵循以下规则:
- extnID:
OBJECT IDENTIFIER
的标签值为0x06
。 - critical:
BOOLEAN
的标签值为0x01
。 - extnValue:
OCTET STRING
的标签值为0x04
。
EXPLICIT 的作用含义
在ASN.1中,EXPLICIT
关键字用于显式地标记一个字段的标签。它的作用是确保在编码时,该字段的标签不会被隐式地省略或改变。EXPLICIT
通常用于在复杂的结构中明确区分不同的字段。
在证书扩展段中,EXPLICIT
用于标记扩展段的存在。由于扩展段是可选的,使用EXPLICIT
可以确保在编码时,扩展段的标签(0xA3
)被显式地包含在编码中,即使扩展段为空。
EXPLICIT 的编码:
- 标签:
0xA3
([3] EXPLICIT
的标签值为0xA3
) - 长度:扩展段的长度
- 值:扩展段的具体内容
例如,如果扩展段包含一个扩展项,其编码为30 0C 06 03 2A 03 04 01 01 FF 04 04 01 02 03 04
,则EXPLICIT
编码为:
- 标签:
0xA3
- 长度:
0x0E
(扩展段的长度为14字节) - 值:
30 0C 06 03 2A 03 04 01 01 FF 04 04 01 02 03 04
- 编码:
A3 0E 30 0C 06 03 2A 03 04 01 01 FF 04 04 01 02 03 04
实际值:
A3820416308204123082017D060A2B06010401D6790204020482016D048201690167007500DDDCCA3495D7E11605E79532FAC79FF83D1C50DFDB003A1412760A2CACBBC82A000001951D90DE34000004030046304402206BC4F94795710AABCA93992DF628D707C199D7C37000EBC4FE27BF73CEC40F6C02202BC7EC88E363BA169BE0CE35D6F26482DEE89C745598020187F468FA1A918A2B0076007D591E12E1782A7B1C61677C5EFDF8D0875C14A04E959EB9032FD90E8C2E79B8000001951D90DDEF000004030047304502207287C9CA3946FBB038768CC9FD1AB23AF277294D7CB9CC2BBC882ACC5BEFC81802210097816A753589A70A69CC285A7A6CD76146F1B8A047B8E560E7F683CEB116E80D0076001A04FF49D0541D40AFF6A0C3BFF1D8C4672F4EECEE234068986B17402EDC897D000001951D90DE5200000403004730450220081A934EDB5C292F509B1F0294A1D194105F549CE9C9FE9199E86D4290BA2E83022100B7337E5305E5CFB5D86F0D447AEAC7B8C8F49543C308D4E99BA17DDF239FF644302706092B060104018237150A041A3018300A06082B06010505070302300A06082B06010505070301303C06092B0601040182371507042F302D06252B060104018237150887BDD71B81E7EB4682819D2E8ED00C87F0DA1D5D82ABE73087EDF11F02016402012D3081B406082B060105050701010481A73081A4307306082B060105050730028667687474703A2F2F7777772E6D6963726F736F66742E636F6D2F706B696F70732F63657274732F4D6963726F736F6674253230417A757265253230525341253230544C5325323049737375696E67253230434125323030342532302D253230787369676E2E637274302D06082B060105050730018621687474703A2F2F6F6E656F6373702E6D6963726F736F66742E636F6D2F6F637370301D0603551D0E041604143A7C1CB9F7B1ACC8F291FA84B4F86D5D5F064CF3300E0603551D0F0101FF0404030205A030200603551D11041930178215737570706F72742E6D6963726F736F66742E636F6D300C0603551D130101FF04023000306A0603551D1F04633061305FA05DA05B8659687474703A2F2F7777772E6D6963726F736F66742E636F6D2F706B696F70732F63726C2F4D6963726F736F6674253230417A757265253230525341253230544C5325323049737375696E67253230434125323030342E63726C30660603551D20045F305D3051060C2B0601040182374C837D01013041303F06082B060105050702011633687474703A2F2F7777772E6D6963726F736F66742E636F6D2F706B696F70732F446F63732F5265706F7369746F72792E68746D3008060667810C010202301F0603551D230418301680143B70D153E976259D60A8CA660FC69BAE6F54166A301D0603551D250416301406082B0601050507030206082B06010505070301 |
证书扩展字段的结构
证书扩展字段的结构如下:Extensions ::= SEQUENCE OF Extension
Extension ::= SEQUENCE {
extnID OBJECT IDENTIFIER, -- 扩展的唯一标识符
critical BOOLEAN DEFAULT FALSE, -- 是否关键扩展
extnValue OCTET STRING -- 扩展的具体值
}
在ASN.1编码中,扩展字段的标签是0xA3
([3] EXPLICIT
),表示这是一个显式标记的扩展段。
解析扩展段
- 标签:
A3
(表示[3] EXPLICIT
,显式标记的扩展段) - 长度:
82 04 16
(表示扩展段的长度为1046字节) - 值:后续的扩展内容。
解析扩展项
每个扩展项的结构为:Extension ::= SEQUENCE {
extnID OBJECT IDENTIFIER,
critical BOOLEAN DEFAULT FALSE,
extnValue OCTET STRING
}
扩展项 1
extnID:
- 标签:
06
(OBJECT IDENTIFIER) - 长度:
0A
(10字节) - 值:
2B 06 01 04 01 D6 79 02 04 02
(OID为1.3.6.1.4.1.311.21.2
,表示证书策略扩展) - 编码:
06 0A 2B 06 01 04 01 D6 79 02 04 02
- 标签:
critical:
未出现,默认为
FALSE
。extnValue:
- 标签:
04
(OCTET STRING) - 长度:
82 01 6D
(365字节) - 值:后续的365字节数据。
- 编码:
04 82 01 6D ...
扩展项 2
- 标签:
extnID:
- 标签:
06
(OBJECT IDENTIFIER) - 长度:
09
(9字节) - 值:
2B 06 01 04 01 82 37 15 0A
(OID为1.3.6.1.4.1.311.21.10
,表示密钥用法扩展) - 编码:
06 09 2B 06 01 04 01 82 37 15 0A
- 标签:
critical:
未出现,默认为
FALSE
。extnValue:
- 标签:
04
(OCTET STRING) - 长度:
04
(4字节) - 值:
03 00 46 30
- 编码:
04 04 03 00 46 30
扩展项 3
- 标签:
extnID:
- 标签:
06
(OBJECT IDENTIFIER) - 长度:
09
(9字节) - 值:
2B 06 01 04 01 82 37 15 07
(OID为1.3.6.1.4.1.311.21.7
,表示增强密钥用法扩展) - 编码:
06 09 2B 06 01 04 01 82 37 15 07
- 标签:
critical:
未出现,默认为
FALSE
。extnValue:
- 标签:
04
(OCTET STRING) - 长度:
2F
(47字节) - 值:后续的47字节数据。
- 编码:
04 2F ...
扩展项 4
- 标签:
extnID:
- 标签:
06
(OBJECT IDENTIFIER) - 长度:
09
(9字节) - 值:
2B 06 01 04 01 82 37 15 08
(OID为1.3.6.1.4.1.311.21.8
,表示CRL分发点扩展) - 编码:
06 09 2B 06 01 04 01 82 37 15 08
- 标签:
critical:
未出现,默认为
FALSE
。extnValue:
- 标签:
04
(OCTET STRING) - 长度:
82 01 69
(361字节) - 值:后续的361字节数据。
- 编码:
04 82 01 69 ...
- 标签:
证书签名算法标识
定义为:
signatureAlgorithm AlgorithmIdentifier, |
实际值为:
30 0D 06092A864886F70D01010C 05 00 |
证书的签名值
定义为:
signatureValue BIT STRING |
实际数据为:
03 820201 005716D5B4CADD4002262CF7FF4677B618298FCB3858E287990F99A25DC7B3415300C63971EBA68A57549A061FFE3316F32D4177A842653F31439E89F55BF549EB0B8109FF65ED3EDB29AFA31688A8ED4A91DDF54B2D5DF248D05480C1D52FA7BC879763C55B2684DC16E7DC4CEA9D0169C246BF22A730867E7921DDA9F90746E9F18E4023072CC03A32C7CBEA36A3F379FA98F1429FEE0607D00F887784C21BE6E8C0E929FE4B9826AC71A7EC33E4DF025C37E13DEB813E881DF52AF2B0700BFF142D35FDCBAFEB54F5C39BE222A0F1557665AB97EFB05CDC323D972D2F313486A4B0C9680BD8E6379E591834DB685856E4D31CA051CEF6C26D07274E5F5DE3E7F945446C6EDF1E8CE4F1653DE91B037E14CEDB70786DB5D32EB89EA6863CB0319142B904577459F20C1CA7CE53B0E06A2CF2B9E4E524B62D17B48F48BAB6A0232081747A4F05212FCC5A5A736FFE0C4FE36BF66542D5FFB45850F91C227743A827E9A93561E8A48214ECEAA969C77FD63EE212E414D5ED1AF629F48AEBD71C8DC4D22DE94470A8A829DDDD1A44B470B68A8080B37BCB741E508BF5349623E818A52FD36DFD7BDC6E4D81882FD44B26D79BA448C4AC7BC80745724BA9D4B0A1B083C2A7177FDDC81BC02A2A460AE3F0A58B8677A6252EEB63C1CDECDF9809E850BE0ED158B7FE20A182424A283E51AE9CB1E4A87843E58C4C016400EFC1DDFF2F |
为什么浏览器上显示的证书内容为 5716
开头而不是 005716
开头
在 DER 编码中,BIT STRING 的第一个字节是填充位数(通常为 0),表示签名数据的对齐方式。浏览器或其他工具在显示证书内容时,通常会忽略这个填充位数,直接从签名数据开始显示。
因此:
- DER 编码的
signatureValue
:以005716
开头,其中00
是填充位数。 - 浏览器显示的
signatureValue
:以5716
开头,因为浏览器忽略了填充位数。
参考文档
https://www.rfc-editor.org/rfc/rfc5280
https://learn.microsoft.com/zh-cn/windows/win32/seccertenroll/about-x-509-public-key-certificates
https://www.cnblogs.com/chnking/archive/2007/08/28/872104.html
https://www.cnblogs.com/xuem/p/12747529.html
https://blog.csdn.net/swordfly369/article/details/84045270
https://rfc2cn.com/rfc5280.html