在解码 TLS 自签名证书中的 SubjectAltName 时,我无法确定语法。我相信证书格式正确。问题是,我不明白如何解码CHOICE
。
首先,SAN 有四个名称:
DNS.1 = example.com
DNS.2 = www.example.com
DNS.3 = mail.example.com
DNS.4 = ftp.example.com
接下来,RFC 5280,p。127说:
SubjectAltName ::= GeneralNames
GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
GeneralName ::= CHOICE {
otherName [0] AnotherName,
rfc822Name [1] IA5String,
dNSName [2] IA5String,
x400Address [3] ORAddress,
directoryName [4] Name,
ediPartyName [5] EDIPartyName,
uniformResourceIdentifier [6] IA5String,
iPAddress [7] OCTET STRING,
registeredID [8] OBJECT IDENTIFIER }
最后,一个十六进制编码的字符串开始于SEQUENCE
:
3041820B6578616D706C652E636F6D820F7777772E6578616D706C652E636F6D82106D61696C2E6578616D706C652E636F6D820F6674702E6578616D706C652E636F6D
我理解30
的是标签,41
是长度。当我打破我看到的价值观时:
820B6578616D706C652E636F6D
820F7777772E6578616D706C652E636F6D
82106D61696C2E6578616D706C652E636F6D
820F6674702E6578616D706C652E636F6D
所以它看起来像82
is CHOICE
,然后是值的长度,然后是值。所有的值都连接在一起。
我的问题是,怎么82
变成了CHOICE
?我不记得以前在 ASN.1 中遇到过它。我如何处理解码?
CHOICE 本身没有实际的标签(它是“透明”类型)——相反,每个可能的内部类型都直接由其自己的标签确定。例如,当您解码 GeneralName 时,iPAddress 由上下文特定标签 7 指示。
标记字节的最高两位表示其类(通用、应用程序、上下文、私有——您可以在外行指南第 3.1 节中找到一个表)。所以 byte
82
对应于 tag[CONTEXT 2]
,或者[2]
简称,这意味着你有一个dNSName。相同的标签也意味着它是一个 IA5String——因为它默认是一个隐式标签,它会覆盖
[universal 22]
一个 IA5String 应该有的通常标签。(这就是为什么openssl asn1parse
只显示“cont [2]”——它没有实际的规范,也不知道它在解码什么。)有时类型已经可以从内置标签中明确确定,例如,同一个 RFC 具有DisplayText,它是四种类型之间的选择,每种类型都具有不同的“通用”标签,因此无需添加自定义标签。