ASN.1八位字节串

8
我正在解码ASN.1格式的X.509证书。我已经成功解码它,遍历了它的结构,但有一件事我不理解。
有些情况下,我会得到一个八位字节字符串,并且我正在使用的网站(http://lapo.it/asn1js/)显示这些八位字节字符串实际上包含更多的ASN.1树形结构。这个网站会用(encapsulates)来注释这样的八位字节字符串。
我的问题是: 在解析过程中如何知道这个八位字节字符串是否真正地封装了其他内容? 我只需要尝试解析它,看看是否得到了一个标签和有效的长度吗?如果没有,那么它只是纯的字节数据吗?如果是,那么它就是一个有效的子树?
还是说应该将其输出为字节,并且只有在消费者知道它是来自特定密钥的编码数据时才尝试解析它?
以网站上已加载的示例为例,点击"解码"按钮。例如,我指的是偏移量为332的八位字节字符串,它封装了一个位字符串。

在这个例子中,偏移量332是keyUsage,它是仅仅是一个位串。一个更有趣的例子可能是subjectAltName 2.5.29.17,在该证书中不存在,但https://google.com/有一个很好的测试解析的例子。 - mr.spuratic
抱歉,只是为了明确一下,我指的是google.com https网站上的证书,它有40多个altNames。这不是一个LMGTFY;-) - mr.spuratic
@mr.spuratic 在这个例子中,偏移量为332的地方有一个包含位串的八位字符串。我的问题是是否有某种规则可以推断出原语封装了其他内容。还是我只需尝试解码它,如果长度和类型都正确,则取解码后的值?或者我会从某些规范中知道像subjectAltName这样的东西总是编码了更多的八位字符串? - Cocoanetics
2个回答

9
这是ASN.1术语中关于“扩展”的定义(RFC 2459 §B.2 — 我知道这个RFC已经过时了,但是这个有用的附录在后续版本中不存在)。
Extensions ::= SEQUENCE OF Extension

Extension ::= SEQUENCE {
extnId     OBJECT IDENTIFIER,
critical   BOOLEAN DEFAULT FALSE,
extnValue  OCTET STRING }

每个扩展负载都被封装在一个OCTET STRING中。扩展的OID告诉您在该八位字节字符串中可以期望什么。 在keyUsage的情况下,它是一个BIT字符串 (§4.2.1.3)。
现在我已经得到了关于subjectAltName的答案,它在§4.2.1.7中。
使用OCTET STRING进行内容的一个好处是,根据规范,未知(非关键)扩展可以被标识为这样,并且可以轻松地跳过它们(尽管我认为DER也可以轻松实现)。

1
这是我很久以来对ASN1问题得到的最好解释。;-) - Cocoanetics
当我解码OCTET STRING时,如果没有可用的DEFN(OID),那么我会测试它是否包含有效的ASN1序列,并且如果有效,则会作为BLOB和CONTAINED序列进行双重解码。 - smallscript
1
请注意,对于CRITICAL:<bool>的情况,DER编码有关于不包括DEFAULT值(冗余)的特殊规则。因此,根据用于扩展的SCHEMA,您可能看不到ASN1中存在BOOLEAN。 - smallscript

2

告诉ASN.1工具处理封装的方法是使用关键字“CONTAINING”。例如(这不是实际/正确的证书规范,但应该能够给您一个想法):

TstCert DEFINITIONS IMPLICIT TAGS ::=
BEGIN
   Sun ::= SEQUENCE {
       subjAltType OBJECT IDENTIFIER,
       name GenNames
   }

   GenNames ::= SEQUENCE SIZE (1..5) OF GenName

   GenName ::= CHOICE {
       otherName   [0] OtherName,
       rfc822Name  [1] UTF8String
   }

   OtherName ::= OCTET STRING (CONTAINING SEQUENCE {
       type-id OBJECT IDENTIFIER,
       value [0] EXPLICIT UTF8String
   } )
END

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接