在解码 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,第页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
,CHOICE
后面跟着值的长度,然后是值。所有值都连接在一起。
我的问题是,怎么会82
变成这样CHOICE
?我不记得以前在 ASN.1 中遇到过这种情况。我该如何处理解码?
答案1
CHOICE 本身没有实际的标签(它是一种“透明”类型)——相反,每个可能的内部类型都直接由其自己的标签决定。例如,当您解码 GeneralName 时,iPAddress 会通过上下文特定的标签 7 来指示。
标签字节的最高两位表示其类别(通用、应用程序、上下文、私有 - 您可以在外行指南节 3.1)。因此,字节82
对应于标签[CONTEXT 2]
,或[2]
简称,这意味着你有一个域名。
相同的标记还意味着它是一个 IA5String – 由于默认情况下它是一个隐式标记,它[universal 22]
会覆盖 IA5String 所具有的通常标记。(这就是为什么openssl asn1parse
只显示“cont [ 2 ]”的原因 – 它没有实际规范并且不知道它正在解码什么。)
有时类型已经可以从内置标签中明确确定,例如相同的 RFC 具有显示文本这是四种类型之间的选择,每种类型已经具有不同的“通用”标签,因此无需添加自定义标签。