ASN1中的[0]和[3]是如何工作的?

12
我正在解码ASN1(用于HTTPS证书的X.509)。我做得很好,但有一件事情我找不到易懂的文档。
在这个 JS ASN1 parser 中,你会看到一个 SEQUENCE 元素下面有一个 [0] 和一个 [3],第一个在数据中看起来像这样:A0 03 02 01 02 ...。我想知道这是什么意思,如何解码它。
另一个例子是 Anatomy of an X.509 v3 Certificate,在前两个 SEQUENCE 元素之后有一个 [0]
我不明白的是 A0 如何符合标签字节的前两位是类、下一位是原始/构造位、其余5位应该是标签类型的方案。A0 是 10100000,这意味着标签类型值将为零。

[0]和[3]是标签的表示(类别为CONTEXT-SPECIFIC,值为0和3)。你似乎理解A0如何编码标签。标签值为0并不罕见。我不确定你在问什么。 - Kevin
我不理解上下文特定的目的...那么[0]的意思是什么? - Cocoanetics
4个回答

17
听起来你需要了解ASN.1标记的介绍。从两个角度来看待这个问题。X.690定义了BER/CER/DER编码规则,因此它回答了如何编码标记的问题。X.680定义了ASN.1本身,因此它定义了标记的语法和规则。这两个规范都可以在ITU-T网站上找到。我会给你一个快速概述。
标记在BER/DER/CER中用于标识类型。它们特别适用于区分SEQUENCE的组件和CHOICE的替代项。
标记结合了标记类和标记号。标记类包括UNIVERSAL、APPLICATION、PRIVATE和CONTEXT-SPECIFIC。UNIVERSAL类基本上用于内置类型。APPLICATION通常用于用户定义的类型。CONTEXT-SPECIFIC通常用于构造类型(SEQUENCE、CHOICE、SEQUENCE OF)中的组件。从语法上讲,在ASN.1模块中指定标记时,它们写在方括号内:[tag_class tag_number];对于CONTEXT-SPECIFIC,tag_class被省略。因此,[APPLICATION 10]或[0]。

虽然每种ASN.1类型都有一个相关联的标签,但从语法上讲,还有“标记类型(TaggedType)”,它由ASN.1作者用于指定要对类型进行编码的标签。基本上,标记类型将一个标签前缀放在一个类型前面。例如:

MyType ::= SEQUENCE {
  field_with_tagged_type [0] UTF8String
}

在TaggedType中的标签可以是显式的或隐式的。如果是显式的,这意味着我希望原始标签被明确编码。如果是隐式的,这意味着我只想让我指定的标签被编码。在显式情况下,BER编码会产生一个嵌套的TLV(标签-长度-值):外部标签(如上例中的[0]),长度,然后是另一个TLV作为值。在该示例中,这个内部TLV将具有UTF8String的[UNIVERSAL 12]标签。
标签是显式还是隐式取决于您如何编写标签以及标记环境。例如:
MyType2 ::= SEQUENCE {
  field_with_explicit_tag [0] EXPLICIT UTF8String OPTIONAL,
  field_with_implicit_tag [1] IMPLICIT UTF8String OPTIONAL,
  field_with_tag [2] UTF8String OPTIONAL
}

如果未指定IMPLICIT或EXPLICIT,则有一些规则定义标记是显式还是隐式(请参见X.680 31)。这些规则考虑了为ASN.1模块定义的标记环境。ASN.1模块可以将标记环境指定为IMPLICIT TAGS、EXPLICIT TAGS或AUTOMATIC TAGS。粗略地说,如果未为标记指定IMPLICIT或EXPLICIT,则在标记环境为EXPLICIT时,标记将为显式,在标记环境为IMPLICIT或AUTOMATIC时,标记将为隐式。自动标记环境基本上与IMPLICIT标记环境相同,只是为SEQUENCE和CHOICE类型的成员自动分配唯一标记。
请注意,在上面的示例中,MyType2的三个组件都是可选的。在BER/CER/DER中,解码器将根据编码的标记知道哪个组件存在(这显然最好是唯一的)。

感谢您的详细解释! - Cocoanetics
你能否评论一下我的问题:http://stackoverflow.com/questions/15624838/what-is-the-effective-tagging-environment-in-case-of-an-imported-type - Norbert Hartl

15
ASN.1 BER和DER使用ASN.1 TAGS来明确地识别编码流中的某些组件。有4类ASN.1标签:通用、应用程序、私有和上下文特定。[0]是一个上下文特定标签,因为它前面没有标签类关键字。通用保留给ASN.1中的内置类型。最常见的是看到上下文特定标签,以消除SEQUENCE中包含可选元素的潜在歧义。如果您知道您接收的是两个不可选的项目,一个跟在另一个后面,即使它们的标记相同,您也知道哪个是哪个。然而,如果第一个是可选的,则这两个必须具有不同的标记,否则,如果只有一个存在于编码中,您将无法确定接收到的是哪一个。
现在大多数情况下,ASN.1规范使用“自动标签”,因此您不必担心消息中这种消除歧义的问题,因为SEQUENCE、SET和CHOICE的组件将自动获得上下文特定标签,从[0]、[1]、[2]等开始为每个组件。
你可以在http://www.oss.com/asn1/resources/books-whitepapers-pubs/asn1-books.html找到更多关于ASN.1标签的信息,那里提供了两本可免费下载的书籍。
另一个非常好的资源是http://asn1-playground.oss.com,在这里你可以在在线编译器和编码/解码器中尝试不同标签的ASN.1规范的变化。在那里,你可以看到标签更改对编码的影响。

如果在编码证书中遇到了明确的上下文标签,比如[0]和[3],那么这是否意味着跳过了第1和第2部分? - Cocoanetics
是的,如果在带有[0]和[3]的字段之间标记为OPTIONAL的SEQUENCE字段,则收到[3]表示消息中不存在OPTIONAL字段。 - Paul Thorpe

2

[0]是一种上下文特定的标记类型,意味着要弄清楚它对字段(如果“Constructed”标志设置)或数据值(如果“Constructed”标志未设置)的含义,您需要知道它出现在什么上下文中。

此外,您还需要知道发送方和接收方在DER流中交换的对象类型,即“ASN.1模块”。

假设他们正在交换证书签名请求,并且[0]作为根序列内部序列的第4个字段出现:

SEQUENCE
    SEQUENCE
        INTEGER 0
        SEQUENCE { ... }
        SEQUENCE { ... }
        [0] { ... }
    }
}

根据RFC2968的规定,该证书签名请求的DER内容定义于附录A中的ASN.1模块。特定字段的含义被巧妙地定义为“属性”并且“应该设置构造标志”。
    attributes    [0] Attributes{{ CRIAttributes }}

你还可以反过来看,通过查看根序列定义(第4节:“顶级类型CertificationRequest”),找到CertificationRequestInfo的位置,并找到CertificationRequestInfo内部“attributes”项目的位置,最后查看它是如何标记的,可以确定“attributes”必须是根序列内第一个序列中的第四个字段,并标记为[0]。

1
谢谢你的回答。一个不错的补充是包含一个指向你所参考文档的链接。 - SherylHohman

2
我最终解决了这个问题,我想为那些仍在努力理解此问题的人提供一些见解。在我的例子中,就像上面的例子一样,我使用的是DER格式的X.509证书。我遇到了“A0 03 02 01 02”序列,并且无法弄清楚它如何转换为版本号2。因此,如果您有同样的问题,以下是其工作原理。

A0告诉您这是一个“上下文特定”字段,“构造”标记,并具有类型值0x00。立即,上下文特定告诉您不要使用DER / BER的正常类型字段。相反,鉴于这是X.509证书,类型值在RFC 5280,第116页中被标记。在那里,您将看到四个带有标记的字段[0],[1],[2]和[3],分别代表“版本”,“发行者唯一标识符”,“主题唯一标识符”和“扩展”。因此,在这种情况下,A0的值告诉您,这是X.509上下文特定字段之一,特别是“版本”类型。这解决了“A0”值的问题。

“03”值只是您期望的长度。

由于此被标识为“构造”,因此数据应表示正常的DER / BER对象。 “02 01 02”是您正在查找的实际版本号,表示为整数。 “02”是整数的标准BER编码,“01”是长度,而“02”是值,或在这种情况下是您的版本号。

因此,鉴于X.509定义了4种上下文特定类型,您应该期望在证书中任何地方看到“A0”,“A1”,“A2”和“A3”。希望上述提供的信息现在更有意义,并帮助您更好地理解这些标记代表什么。


关于“您应该在证书的任何地方看到“A0”,“A1”,“A2”和“A3””,我认为它们必须出现在指定的确切位置,而不是随机位置。SEQUENCEs不是随机的。 - jww

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